如何在 Windows 中自动销毁子进程?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/53208/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 05:14:29  来源:igfitidea点击:

How do I automatically destroy child processes in Windows?

windowsprocess

提问by jm.

In C++ Windows app, I launch several long running child processes (currently I use CreateProcess(...) to do this.

在 C++ Windows 应用程序中,我启动了几个长时间运行的子进程(目前我使用 CreateProcess(...) 来执行此操作。

I want the child processes to be automatically closed if my main processes crashesor is closed.

如果我的主进程崩溃或关闭,我希望子进程自动关闭。

Because of the requirement that this needs to work for a crash of the "parent", I believe this would need to be done using some API/feature of the operating system. So that all the "child" processes are cleaned up.

由于需要为“父”崩溃而工作,因此我认为这需要使用操作系统的某些 API/功能来完成。这样所有的“子”进程都被清理干净。

How do I do this?

我该怎么做呢?

回答by jm.

The Windows API supports objects called "Job Objects". The following code will create a "job" that is configured to shut down all processes when the main application ends (when its handles are cleaned up). This code should only be run once.:

Windows API 支持称为“作业对象”的对象。以下代码将创建一个“作业”,该作业被配置为在主应用程序结束时(当其句柄被清理时)关闭所有进程。此代码应该只运行一次。:

HANDLE ghJob = CreateJobObject( NULL, NULL); // GLOBAL
if( ghJob == NULL)
{
    ::MessageBox( 0, "Could not create job object", "TEST", MB_OK);
}
else
{
    JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 };

    // Configure all child processes associated with the job to terminate when the
    jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
    if( 0 == SetInformationJobObject( ghJob, JobObjectExtendedLimitInformation, &jeli, sizeof(jeli)))
    {
        ::MessageBox( 0, "Could not SetInformationJobObject", "TEST", MB_OK);
    }
}

Then when each child process is created, execute the following code to launch each child each process and add it to the job object:

然后在创建每个子进程时,执行以下代码以启动每个子进程并将其添加到作业对象:

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;

// Launch child process - example is notepad.exe
if (::CreateProcess( NULL, "notepad.exe", NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
    ::MessageBox( 0, "CreateProcess succeeded.", "TEST", MB_OK);
    if(ghJob)
    {
        if(0 == AssignProcessToJobObject( ghJob, processInfo.hProcess))
        {
            ::MessageBox( 0, "Could not AssignProcessToObject", "TEST", MB_OK);
        }
    }

    // Can we free handles now? Not sure about this.
    //CloseHandle(processInfo.hProcess); 
    CloseHandle(processInfo.hThread);
}

VISTA NOTE: See AssignProcessToJobObject always return "access denied" on Vistaif you encounter access-denied issues with AssignProcessToObject() on vista.

VISTA 注意:如果在 Vista 上遇到 AssignProcessToObject() 拒绝访问问题,请参阅AssignProcessToJobObject 在 Vista 上总是返回“访问被拒绝”

回答by Rob Walker

One somewhat hackish solution would be for the parent process to attach to each child as a debugger (use DebugActiveProcess). When a debugger terminates all its debuggee processes are terminated as well.

一种有点骇人听闻的解决方案是让父进程作为调试器附加到每个子进程(使用DebugActiveProcess)。当调试器终止时,它的所有被调试进程也将终止。

A better solution (assuming you wrote the child processes as well) would be to have the child processes monitor the parent and exit if it goes away.

更好的解决方案(假设您也编写了子进程)是让子进程监视父进程并在它消失时退出。

回答by Adam Mitz

Windows Job Objects sounds like a good place to start. The name of the Job Object would have to be well-known, or passed to the children (or inherit the handle). The children would need to be notice when the parent dies, either through a failed IPC "heartbeat" or just WFMO/WFSO on the parent's process handle. At that point any child process could TermianteJobObject to bring down the whole group.

Windows Job Objects 听起来是个不错的起点。作业对象的名称必须是众所周知的,或者传递给子对象(或继承句柄)。当父进程死亡时,子进程需要得到通知,无论是通过失败的 IPC“心跳”还是父进程句柄上的 WFMO/WFSO。此时,任何子进程都可以使用 TerianteJobObject 来关闭整个组。

回答by Pedro

You can keep a separate watchdog process running. Its only task is watching the current process space to spot situations like you describe. It could even re-launch the original application after a crash or provide different options to the user, collect debug information, etc. Just try to keep it simple enough so that you don't need a second watchdog to watch the first one.

您可以保持一个单独的看门狗进程运行。它唯一的任务是观察当前的进程空间以发现您所描述的情况。它甚至可以在崩溃后重新启动原始应用程序或为用户提供不同的选项、收集调试信息等。只要尽量保持简单,这样您就不需要第二个看门狗来监视第一个。

回答by Kibbee

You'd probably have to keep a list of the processes you start, and kill them off one by one when you exit your program. I'm not sure of the specifics of doing this in C++ but it shouldn't be hard. The difficult part would probably be ensuring that child processes are shutdown in the case of an application crash. .Net has the ability to add a function that get's called when an unhandled exception occurs. I'm not sure if C++ offers the same capabilities.

您可能必须保留一份您启动的进程的列表,并在您退出程序时将它们一个一个地杀死。我不确定在 C++ 中执行此操作的具体细节,但应该不难。困难的部分可能是确保在应用程序崩溃的情况下关闭子进程。.Net 能够添加一个函数,当发生未处理的异常时调用该函数。我不确定 C++ 是否提供相同的功能。

回答by Adam Pierce

You could encapsulate each process in a C++ object and keep a list of them in global scope. The destructors can shut down each process. That will work fine if the program exits normally but it it crashes, all bets are off.

您可以将每个进程封装在一个 C++ 对象中,并在全局范围内保留它们的列表。析构函数可以关闭每个进程。如果程序正常退出但它崩溃了,那将工作正常,所有赌注都关闭了。

Here is a rough example:

这是一个粗略的例子:

class myprocess
{
public:
    myprocess(HANDLE hProcess)
        : _hProcess(hProcess)
    { }

    ~myprocess()
    {
        TerminateProcess(_hProcess, 0);
    }

private:
    HANDLE _hProcess;
};

std::list<myprocess> allprocesses;

Then whenever you launch one, call allprocessess.push_back(hProcess);

然后每当你启动一个,调用 allprocessess.push_back(hProcess);

回答by Daemin

Just off the top of my head:

就在我的头顶:

  • Have you considered using threads instead of processes?
  • Try passing the handle of the main thread/process to the child processes and get them to wait on that handle. This works for threads, as waiting on a thread handle waits until that thread completes and exits. Not too sure if it'll work for processes, should check out MSDN to verify this.
  • 您是否考虑过使用线程而不是进程?
  • 尝试将主线程/​​进程的句柄传递给子进程并让它们等待该句柄。这适用于线程,因为等待线程句柄会等待该线程完成并退出。不太确定它是否适用于进程,应该查看 MSDN 来验证这一点。