将Ctrl + C消息发送到没有窗口的进程

时间:2016-06-27 13:05:04

标签: c# windows api process message

从我的程序中我需要在后台运行一个外部控制台程序:

p = new Process()
{
    StartInfo = new ProcessStartInfo()
    {
        FileName = "someConsoleApplication.exe",
        Arguments = "someArguments",
        UseShellExecute = false,
        CreateNoWindow = true,
        RedirectStandardError = true,
        RedirectStandardOutput = true,
    }
};
p.Start();

有效。该程序在后台运行,完成其工作然后退出。 但在某些情况下,我需要在程序运行时停止它。这就是问题所在。如果我做

p.Kill();

程序退出而不保存数据。 所以我需要一些方法来询问"程序退出,而不是杀死它。当我在没有" CreateNoWindow"的情况下运行它时,如果我关闭窗口或按Ctrl + C,它将正确退出。我已尝试在后台模式(使用Windows API)时直接向程序发送Ctrl + C消息,但似乎程序无法在没有窗口时处理此类消息

我也找到了一个不太好的方法:

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GenerateConsoleCtrlEvent(ConsoleCtrlEvent sigevent, int dwProcessGroupId);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();

public enum ConsoleCtrlEvent
{
    CTRL_C = 0,
    CTRL_BREAK = 1,
    CTRL_CLOSE = 2,
    CTRL_LOGOFF = 5,
    CTRL_SHUTDOWN = 6
}

private void CrackingProcessCleanKill()
{
    if (AttachConsole((uint)p.Id))
    {
        SetConsoleCtrlHandler(null, true);
        GenerateConsoleCtrlEvent(ConsoleCtrlEvent.CTRL_C, 0);
        FreeConsole();
        SetConsoleCtrlHandler(null, false);
    }
}

但有时它会不可预测地导致整个应用程序关闭,而不仅仅是进程p。它也不是一个好的解决方案,因为该代码不能用于单元测试(或者可能是我的错误?)。我的意思是它在从真实应用程序中使用时起作用,并在从单元测试中使用时抛出异常。

那么,做正题的正确方法是什么?

0 个答案:

没有答案