Stop console process using Ctrl+C.

https://msdn.microsoft.com/en-us/library/ms686016(VS.85).aspx
private void Button1_OnClick(object sender, RoutedEventArgs e)
        {
            var file = new FileInfo(@"C:\temp\video.mp4");
            if (file.Exists)
            {
                file.Delete();
            }
            ct = new CancellationTokenSource();
            Task.Factory.StartNew(() =>
            {
                var pInfo = new ProcessStartInfo("cmd.exe",
                    string.Format("/c {0} \"{1}\"", new object[] {"adb.bat", file.Name}));
                pInfo.CreateNoWindow = true;
                pInfo.UseShellExecute = false;
                pInfo.RedirectStandardError = true;
                pInfo.RedirectStandardOutput = true;
                pInfo.RedirectStandardInput = true;

                var p = Process.Start(pInfo);

                ct.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(10));
                try
                {
                    if (p.HasExited)
                    {
                        Trace.WriteLine("terminated normally");
                    }
                    else
                    {
                        NativeMethods.StopProgram(p);
                        p.StandardInput.WriteLine(string.Format("Y"));
                        p.WaitForExit(1000);
                    }
                    outmsg = p.StandardOutput.ReadToEnd();
                    errmsg = p.StandardError.ReadToEnd();
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception);
                }

                Trace.WriteLine(outmsg);
                Trace.WriteLine(errmsg);
                return 1;
            }, ct.Token, TaskCreationOptions.None, TaskScheduler.Default)
                .ContinueWith(
                    r =>
                    {
                        TextBlock1.Text += outmsg;
                        TextBlock1.Text += errmsg;

                        var p = Process.Start(new ProcessStartInfo("cmd.exe", "/c pull.bat " + file.FullName));
                        p.WaitForExit();

                        var p2 = Process.Start(new ProcessStartInfo(file.FullName));
                        ct.Dispose();
                    }, TaskScheduler.FromCurrentSynchronizationContext());
        }

      internal static class NativeMethods
    {
        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetConsoleCtrlHandler(
            [In] [Optional] [MarshalAs(UnmanagedType.FunctionPtr)] HandlerRoutine HandlerRoutine,
            [In] [MarshalAs(UnmanagedType.Bool)] bool Add);

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool AttachConsole(uint dwProcessId);

        [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
        private static extern bool FreeConsole();

        [DllImport("kernel32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);

        public static void StopProgram(Process proc)
        {
            //This does not require the console window to be visible.
            if (AttachConsole((uint) proc.Id))
            {
                //Disable Ctrl-C handling for our program
                SetConsoleCtrlHandler(null, true);
                GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);

                //Must wait here. If we don't and re-enable Ctrl-C
                //handling below too fast, we might terminate ourselves.
                proc.WaitForExit(2000);

                FreeConsole();

                //Re-enable Ctrl-C handling or any subsequently started
                //programs will inherit the disabled state.
                SetConsoleCtrlHandler(null, false);
            }
        }

        // Enumerated type for the control messages sent to the handler routine

        private enum CtrlTypes : uint
        {
            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT,
            CTRL_CLOSE_EVENT,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT
        }

        internal enum ControlSignalType : uint
        {
            CTRL_C_EVENT = 0,
            CTRL_BREAK_EVENT = 1,
            CTRL_CLOSE_EVENT = 2,
            CTRL_LOGOFF_EVENT = 5,
            CTRL_SHUTDOWN_EVENT = 6
        }

        [return: MarshalAs(UnmanagedType.Bool)]
        internal delegate bool HandlerRoutine([In] [MarshalAs(UnmanagedType.U4)] ControlSignalType dwCtrlType);
    }

댓글

이 블로그의 인기 게시물

Oracle NLS_DATE_FORMAT 변경

Alternative to IValueConvert, QuickConverter

Reflection with IDispatch-based COM objects