在Windows上将CTRL + C发送到子进程树

时间:2009-11-25 17:54:14

标签: windows

我想运行任意基于控制台的子流程,并从单个主流程管理它们。基于控制台的子进程通过stdin,stdout和stderr进行通信,如果在真正的控制台中运行它们,则在按CTRL + C时它们会完全终止。其中一些实际上可能是一个进程树,例如运行可执行文件的批处理脚本,该可执行文件又可以运行另一个可执行文件来完成某些工作。我想重定向他们的标准I / O(例如,以便我可以在GUI窗口中显示他们的输出)并且在某些情况下向他们发送CTRL + C事件,以便他们放弃并彻底终止。

以下两个图首先显示了正常结构 - 一个主进程有四个工作子进程,其中一些有自己的子进程;然后当其中一个工作人员需要停止时应该发生什么 - 它和它的所有孩子应该得到CTRL + C事件,但没有其他进程应该收到CTRL + C事件。

Process diagram
(来源:livejournal.com

此外,我更希望用户看不到额外的窗口。

这是我尝试过的(注意我在使用Python,但C的解决方案仍然有用):

  • 使用CREATE_NEW_CONSOLE生成一个额外的中间进程,然后让它生成工作进程。然后在我们要杀死工人时调用GenerateConsoleCtrlEventCTRL_C_EVENT,0)。不幸的是,CREATE_NEW_CONSOLE似乎阻止我重定向标准I / O通道,所以我没有简单的方法将输出恢复到主程序。
  • 使用CREATE_NEW_PROCESS_GROUP生成一个额外的中间进程,然后让它生成工作进程。然后在我们要杀死工人时调用GenerateConsoleCtrlEventCTRL_C_EVENT,0)。不知何故,这设法将CTRL + C 发送到主进程,这是完全没用的。仔细观察,GenerateConsoleCtrlEvent表示无法将CTRL + C发送到进程组。
  • 使用CREATE_NEW_PROCESS_GROUP生成子流程。然后调用GenerateConsoleCtrlEventCTRL_BREAK_EVENT,pid)来杀死该工作人员。这并不理想,因为CTRL + BREAK不如CTRL + C友好,可能会导致终止混乱。 (例如,如果它是一个Python进程,则不能捕获KeyboardInterrupt,也不会运行finally块。)

有什么好方法可以做我想要的吗?我可以看到我可以理论上在第一次尝试时构建并找到其他方法在进程之间进行通信,但我担心它会变得非常尴尬。是否有其他程序可以达到同样效果的好例子?看起来很简单,不能满足这一要求。

1 个答案:

答案 0 :(得分:1)

我不知道管理/重定向stdin等。 al。,但用于管理子进程树 你考虑过使用Windows Job Objects api吗?

还有其他几个关于管理流程树的问题(How do I automatically destroy child processes in Windows? Performing equivalent of “Kill Process Tree” in c++ on windows),如果可以使用它,它看起来就像是最干净的方法。

Windows Via C/C++ by Jeffery Richter的第5章对使用CreateJobObject和相关API进行了很好的讨论。