在Windows上运行任意子进程,仍然干净终止吗? [英] Run arbitrary subprocesses on Windows and still terminate cleanly?

查看:126
本文介绍了在Windows上运行任意子进程,仍然干净终止吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an application A that I would like to be able to invoke arbitrary other processes as specified by a user in a configuration file.

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

Batch script B is one such process a user would like to be invoked by A. B sets up some environment variables, shows some messages and invokes a compiler C to do some work.

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

Does Windows provide a standard way for arbitrary processes to be terminated cleanly? Suppose A is run in a console and receives a CTRL+C. Can it pass this on to B and C? Suppose A runs in a window and the user tries to close the window, can it cancel B and C?

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

TerminateProcess is an option, but not a very good one. If A uses TerminateProcess on B, C keeps running. This could cause nasty problems if C is long-running, since we might start another instance of C to operate on the same files while the first instance of C is still secretly at work. In addition, TerminateProcess doesn't result in a clean exit.

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

GenerateConsoleCtrlEvent sounds nice, and might work when everything's running in a console, but the documentation says that you can only send CTRL+C to your own console, and so wouldn't help if A were running in a window.

在Windows上是否有与SIGINT等效的产品?我很想找到这样的文章: http://www.cons.org/cracauer/sigint.html (适用于Windows).

Is there any equivalent to SIGINT on Windows? I would love to find an article like this one: http://www.cons.org/cracauer/sigint.html for Windows.

推荐答案

我想我在这个问题上有点迟了,但是我还是会为遇到相同问题的任何人写点东西.

I guess I'm a bit late on this question but I'll write something anyway for anyone having the same problem.

我的问题相似,因为我希望我的应用程序是GUI应用程序,但是执行的进程应在没有附加任何交互式控制台窗口的情况下在后台运行.

My problem is similar in that I'd like my application to be a GUI application but the processes executed should be run in the background without any interactive console window attached.

我设法使用GenerateConsoleCtrlEvent()解决了这个问题.棘手的部分是,该文档对如何使用以及如何使用的陷阱尚不十分清楚.

I managed to solve this using GenerateConsoleCtrlEvent(). The tricky part is just that the documentation is not really clear on exactly how it can be used and the pitfalls with it.

我的解决方案基于

My solution is based on what is described here. But that didn't really explain all the details either, so here is the details on how to get it working.

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

  1. Create a new helper application "Helper.exe". This application will sit between your application (parent) and the child process you want to be able to close. It will also create the actual child process. You must have this "middle man" process or GenerateConsoleCtrlEvent() will fail.

使用某种IPC机制从父级与帮助程序进程进行通信,即帮助程序应关闭子进程.当帮助程序收到此事件时,它将调用"GenerateConsoleCtrlEvent(CTRL_BREAK,0)",它会关闭自身和子进程.我为此使用了一个事件对象,当要取消子进程时,父进程会完成该事件对象.

Use some kind of IPC mechanism to communicate from the parent to the helper process that the helper should close the child process. When the helper get this event it calls "GenerateConsoleCtrlEvent(CTRL_BREAK, 0)" which closes down itself and the child process. I used an event object for this myself which the parent completes when it wants to cancel the child process.

要创建您的Helper.exe,请使用CREATE_NO_WINDOW和CREATE_NEW_PROCESS_GROUP创建它. 在创建子进程时,请不要创建任何标志(0),这意味着它将从其父级派生控制台.否则,将忽略事件.

To create your Helper.exe create it with CREATE_NO_WINDOW and CREATE_NEW_PROCESS_GROUP. And when creating the child process create it with no flags (0) meaning it will derive the console from its parent. Failing to do this will cause it to ignore the event.

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

It is very important that each step is done like this. I've been trying all different kinds of combinations but this combination is the only one that works. You can't send a CTRL_C event. It will return success but will be ignored by the process. CTRL_BREAK is the only one that works. Doesn't really matter since they will both call ExitProcess() in the end.

您也不能直接使用子进程ID的进程分组ID调用GenerateConsoleCtrlEvent(),以允许帮助程序进程继续运行.这也会失败.

You also can't call GenerateConsoleCtrlEvent() with a process groupd id of the child process id directly allowing the helper process to continue living. This will fail as well.

我花了一整天的时间来使它工作.此解决方案对我有用,但是如果有人要添加其他内容,请执行.我在网上找到了很多类似问题的人,但是并没有确定的解决方案. GenerateConsoleCtrlEvent()的工作方式也有些怪异,因此,如果有人知道它的更多详细信息,请分享.

I spent a whole day trying to get this working. This solution works for me but if anyone has anything else to add please do. I went all other the net finding lots of people with similar problems but no definite solution to the problem. How GenerateConsoleCtrlEvent() works is also a bit weird so if anyone knows more details on it please share.

这篇关于在Windows上运行任意子进程,仍然干净终止吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆