在Windows上运行任意子进程并仍然干净地终止?

Wee*_*ble 14 windows copy-paste process long-running-processes

我有一个应用程序A,我希望能够在配置文件中调用用户指定的任意其他进程.

批处理脚本B是用户希望由A调用的一个这样的过程.B设置一些环境变量,显示一些消息并调用编译器C来完成一些工作.

Windows是否为任意进程提供了一种标准的方式来彻底终止?假设A在控制台中运行并接收CTRL + C. 它可以传递给B和C吗?假设A在窗口中运行并且用户试图关闭窗口,它可以取消B和C吗?

TerminateProcess是一个选项,但不是一个很好的选项.如果A在B上使用TerminateProcess,则C继续运行.如果C长时间运行,这可能会导致令人讨厌的问题,因为我们可能会启动另一个C实例来操作相同的文件,而C的第一个实例仍在秘密工作.此外,TerminateProcess不会导致干净的退出.

GenerateConsoleCtrlEvent听起来不错,并且可以在控制台中运行所有内容时工作,但文档说您只能将CTRL + C发送到您自己的控制台,因此如果A在窗口中运行则无济于事.

在Windows上是否有任何等效的SIGINT?我很想找到像这样的文章:http://www.cons.org/cracauer/sigint.html for Windows.

Sha*_*kta 9

我想我在这个问题上有点晚了,但无论如何我会为有同样问题的人写点什么.

我的问题类似于我希望我的应用程序是一个GUI应用程序,但执行的进程应该在后台运行,而不附加任何交互式控制台窗口.

我设法使用GenerateConsoleCtrlEvent()来解决这个问题.棘手的部分只是文档不清楚它究竟是如何使用的,以及它的缺陷.

我的解决方案基于此处描述的内容.但这并没有真正解释所有细节,所以这里有关于如何使其工作的细节.

  1. 创建一个新的帮助应用程序"Helper.exe".此应用程序将位于您的应用程序(父级)和您希望能够关闭的子进程之间.它还将创建实际的子进程.你必须有这个"中间人"进程或GenerateConsoleCtrlEvent()将失败.

  2. 使用某种IPC机制从父进程到辅助进程的通信,助手应该关闭子进程.当帮助程序获得此事件时,它调用"GenerateConsoleCtrlEvent(CTRL_BREAK,0)",它关闭自身和子进程.我自己使用了一个事件对象,父进程在想要取消子进程时完成.

要创建Helper.exe,请使用CREATE_NO_WINDOW和CREATE_NEW_PROCESS_GROUP创建它.并且在创建子进程时创建它没有标志(0)意味着它将从其父进程派生控制台.如果不这样做将导致它忽略该事件.

每个步骤都是这样完成的非常重要.我一直在尝试各种不同的组合,但这种组合是唯一有效的组合.您无法发送CTRL_C事件.它将返回成功但将被该过程忽略.CTRL_BREAK是唯一可行的.没关系,因为他们最终都会调用ExitProcess().

您也无法使用子进程ID的进程groupd id直接调用GenerateConsoleCtrlEvent(),以允许帮助程序进程继续生效.这也将失败.

我花了一整天努力让这个工作.这个解决方案适合我,但如果有人有任何其他要添加,请做.我去了所有其他网络发现很多人有类似的问题,但没有明确的解决方案.GenerateConsoleCtrlEvent()如何工作也有点奇怪,所以如果有人知道它的更多细节请分享.

  • 请注意,无法保证在收到Ctrl + C时进程B或C将完全退出. (3认同)

Kin*_*gon 8

正如@Shakta所说GenerateConsoleCtrlEvent()的那样非常棘手,但是你可以在没有帮助程序的情况下发送Ctrl + C.

void SendControlC(int pid)
{
    AttachConsole(pid); // attach to process console
    SetConsoleCtrlHandler(NULL, TRUE); // disable Control+C handling for our app
    GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0); // generate Control+C event
}
Run Code Online (Sandbox Code Playgroud)