代码之家  ›  专栏  ›  技术社区  ›  Weeble

在Windows上运行任意子进程,是否仍能干净地终止?

  •  14
  • Weeble  · 技术社区  · 15 年前

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

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

    Windows是否为任意进程提供了一种干净终止的标准方法?假设A在控制台中运行,并接收到一个ctrl+c。它能把这个传递给b和c吗?假设A在一个窗口中运行,并且用户试图关闭该窗口,它能取消B和C吗?

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

    generateConsolevent听起来不错,当所有东西都在控制台中运行时,它可能会工作,但是文档说您只能将ctrl+c发送到您自己的控制台,因此如果a在窗口中运行,它将不会有帮助。

    在Windows上是否有类似sigint的内容?我想找一篇这样的文章: http://www.cons.org/cracauer/sigint.html 对于Windows。

    2 回复  |  直到 12 年前
        1
  •  9
  •   Shakta    15 年前

    我想我在这个问题上有点晚了,但不管怎样,我还是会为有同样问题的人写一些东西。

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

    我用generateConsolectLevel()解决了这个问题。棘手的部分是,文档并没有真正清楚地说明如何使用它以及它的缺陷。

    我的解决方案基于所描述的内容 here .但这也不能真正解释所有的细节,所以这里是如何让它工作的细节。

    1. 创建新的助手应用程序“helper.exe”。此应用程序将位于应用程序(父进程)和要关闭的子进程之间。它还将创建实际的子进程。您必须有这个“中间人”进程,否则generateConsolectLevel()将失败。

    2. 使用某种IPC机制从父进程向帮助程序进程通信,帮助程序应关闭子进程。当帮助程序得到这个事件时,它调用“generateConsolectLevelnt(ctrl_break,0)”,它关闭自身和子进程。我自己为此使用了一个事件对象,当父进程想要取消子进程时,父进程会完成该对象。

    要创建helper.exe,请使用create_no_窗口创建它,然后创建新的_process_组。 当创建子进程时,不使用标志(0)创建它,这意味着它将从其父进程派生控制台。如果不这样做,将导致它忽略该事件。

    每一步都这样做是非常重要的。我尝试过各种不同的组合,但这种组合是唯一有效的。不能发送ctrl_c事件。它将返回成功,但将被进程忽略。ctrl-break是唯一有效的。并不重要,因为它们最终都会调用exitprocess()。

    您也不能使用子进程ID的进程组ID直接调用GenerateConnectLevelent(),从而允许帮助进程继续活动。这也会失败。

    我花了一整天的时间来做这个工作。这个解决方案对我有用,但是如果有人需要添加什么,请做。我上网发现很多人都有类似的问题,但没有明确的解决办法。generateConsolectLevelent()的工作方式也有点奇怪,因此如果有人知道更多关于它的详细信息,请分享。

        2
  •  8
  •   KindDragon    12 年前

    正如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
    }