我有一些控制台应用程序,我想在我的C#WinForms应用程序中对其进行控制。
基本上,我已经完成了几乎所有的工作,除了关闭我启动的过程。
启动过程时,我已经设置了所有内容,所以:
process.StartInfo.FileName = @"file.exe";
process.StartInfo.WorkingDirectory = Environment.CurrentDirectory;
process.StartInfo.Arguments = "";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true; // important - want to grab stdout
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
process.StandardInput.AutoFlush = true;
stdout已正确重定向。
我已经准备好发送stdin消息,但是我的进程没有收到它们或忽略它们(尚不确定)。
我看到了两个潜在的问题(当然还有我的代码中的问题;))
进程正在启动他的子进程,可能stdin必须直接指向该子进程,但它不是我直接产生的。
可能不仅我必须向子进程发送消息,而且还要向整个组发送消息。但是process.Start根本不与组打交道,因此我现在无法对此进行控制。
问题可能与CreateNoWindow有关,这对我很重要。
process.Close();
也没有做好他的工作。
process.Kill();
在工作,但是它仅杀死由我启动的进程,由我启动的进程产生的子进程-保持活动状态。
最后-我能够杀死所有进程,方法是获取它们的ID并打电话将其一一杀死,但是杀死进程会破坏它们的工作,这对我来说是个问题。我想向他们发送信号以使其关闭,如果它们不响应,则最终将其杀死。
我的尝试是:
1。
process.StandardInput.WriteLine("\x3");
process.StandardInput.Close();
process.Close();
2。
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);
[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleCtrlHandler(HandlerRoutine handler, bool add);
FreeConsole();
if (AttachConsole((uint)process.Id))
{
SetConsoleCtrlHandler(null, true);
GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, (uint)Process.Id);
FreeConsole();
SetConsoleCtrlHandler(null, false);
}
我还尝试对由我启动的进程产生的子进程执行StandardInput.WriteLine
,但是我当然遇到了一个错误,因为我没有重定向标准输入,所以我不能这样做。
我几乎耗尽了所有想法。想过要使用某种SendMessageA并尝试按击Ctrl + C吗?
我知道,如果我直接从cmd.exe开始尝试抓取的进程,则Ctrl + C可以正常工作,并且我可以停止应用程序。
编辑1
更多详细信息。
我已经确认我能够将自己附加到两个子进程的控制台上-一个由我启动,另一个由我启动。
GenerateConsoleCtrlEvent
报告两者均正确,但仍无人关闭。
另一方面,CTRL_BREAK_EVENT似乎已被接受o_O但是我的主窗口也正在关闭,并且似乎该事件没有正常关闭,而是等效的终止操作...
编辑2
PostMessage和SendMessage似乎不能很好地工作,但可以得到任何帮助。
编辑3
最后是taskkill的输出,这也许可以说明情况吗?
taskkill /PID 13384 /T
ERROR: The process with PID 5456 (child process of PID 13384) could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process with PID 14188 (child process of PID 13384) could not be terminated.
Reason: This process can only be terminated forcefully (with /F option).
ERROR: The process with PID 13384 (child process of PID 5152) could not be terminated.
Reason: One or more child processes of this process were still running.
编辑4
我已将CreateNoWindow速度设置为false。
这使我可以用process.CloseMainWindow()
关闭子应用程序,但是仍然没有其他方法可以工作(GenerateConsoleCtrlEvent,proc.StandardInput.WriteLine("\x3")
,带有keybd_event的SendMessage,PostMessage)。
我被困住了。