从我的程序中我需要在后台运行一个外部控制台程序:
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。它也不是一个好的解决方案,因为该代码不能用于单元测试(或者可能是我的错误?)。我的意思是它在从真实应用程序中使用时起作用,并在从单元测试中使用时抛出异常。
那么,做正题的正确方法是什么?