如何将Ctrl + C信号发送到使用CreateNoWindow标志创建的控制台进程

时间:2011-08-10 13:41:12

标签: vb.net process signals

如果我使用Process.Kill(),则该进程被终止。但是,我想终止它。

我尝试使用GenerateConsoleCtrlEvent(ConsoleCtrlEvent.CTRL_C, Process.Id) API,但没有成功。

如果我将False设置为CreateNoWindow标记,当我从键盘发送Ctrl + C时,程序会显示"Caught signal: 2; Terminating"。所以它等待“2”信号终止。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

有一个解决方案。我会试着为你描述一下:

当您编写包装整个控制台的应用程序时 - 控制台由于某种原因无法接收控制代码(问题转到Microsoft),但控制台仍然可以接收这些事件。怎么样?来自外部应用程序。

这是cas.exe的代码

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace ConsoleAppStopper
{
    class cas
    {
        [STAThread]
        static void Main( string[] args )
        {
            if (args.Length < 2)
            {
                Help ();
                return;
            }
            int processId = int.Parse (args[0]);
            ConsoleCtrlEvent CtrlEvent = (ConsoleCtrlEvent)int.Parse(args[1]);

            FreeConsole ();
            AttachConsole (processId);
            GenerateConsoleCtrlEvent (CtrlEvent, 0);
        }

        static void Help()
        {
            Console.BackgroundColor = ConsoleColor.Black;
            Console.ForegroundColor = ConsoleColor.DarkYellow;
            Console.WriteLine ("Console Application Eventer(Stopper)");
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine ("cas.exe ProcessId ControlEvent");
            Console.WriteLine ("Events:");
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine ("\tCTRL_C - 0");
            Console.WriteLine ("\tCTRL_BREAK - 1");
            Console.WriteLine ("\tCTRL_LOGOFF - 5");
            Console.ResetColor ();
        }

        public enum ConsoleCtrlEvent
        {
            CTRL_C = 0, // From wincom.h
            CTRL_BREAK = 1,
            CTRL_CLOSE = 2,
            CTRL_LOGOFF = 5,
            CTRL_SHUTDOWN = 6
        }
        [DllImport ("kernel32.dll")]
        static extern bool GenerateConsoleCtrlEvent( ConsoleCtrlEvent sigevent,
        int dwProcessGroupId );

        [DllImport ("kernel32.dll")]
        static extern bool FreeConsole();

        [DllImport ("kernel32.dll")]
        static extern bool AttachConsole( int dwProcessId ); 
    }
}

以及如何使用它:

public void SendConsoleEvent( ConsoleCtrlEvent ev )
{
    if (!Running)
        return;

    try
    {
        String current_dir = System.Environment.CurrentDirectory;
        String stopper = "cas.exe";
        String args = pr.Id + " " + (int)ev;

        CommandExecutor ex = new CommandExecutor (null, null);
        ex.Start (current_dir, stopper, args);
        // sometimes stop prevent CAS do work. just throw cas and forget about
        //Timer.DelayCall (TimeSpan.FromSeconds (10), ex.Stop);
        //ex.Stop ();
    }
    catch (Exception e)
    {
        Log ("SendConsoleEvent: " + e.ToString ());
    }
}

这里,CommandExecutor是我围绕Process的线程包装器。 pr.Id是以前使用Process Console启动的ID(我们需要发送CTRL_C或其他事件