在C ++ Windows应用程序中,我启动了几个长时间运行的子进程(目前我使用CreateProcess(...)来执行此操作。
如果主进程崩溃或已关闭,我希望子进程自动关闭。
由于要求这需要对“父”的崩溃起作用,我认为这需要使用操作系统的某些API /功能来完成。这样就可以清理所有“子”进程。
我该怎么做?
答案 0 :(得分:70)
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);
}
}
然后,当创建每个子进程时,执行以下代码以启动每个进程并将其添加到作业对象:
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注意:如果您在vista上遇到与AssignProcessToObject()的访问被拒绝问题,请参阅AssignProcessToJobObject always return "access denied" on Vista。
答案 1 :(得分:5)
一个有点hackish的解决方案是父进程作为调试器附加到每个子进程(使用DebugActiveProcess)。当调试器终止时,它的所有调试对象进程也会终止。
更好的解决方案(假设你也编写了子进程)将让子进程监视父进程并在它消失时退出。
答案 2 :(得分:3)
Windows作业对象听起来像是一个很好的起点。作业对象的名称必须是众所周知的,或传递给子对象(或继承句柄)。当父母去世时,孩子需要注意,无论是通过失败的IPC“心跳”,还是父母的过程句柄上的WFMO / WFSO。此时,任何子进程都可以通过TermianteJobObject来关闭整个组。
答案 3 :(得分:0)
您可以保持单独的监视程序进程运行。它唯一的任务是观察当前的流程空间,以发现您描述的情况。它甚至可以在崩溃后重新启动原始应用程序,或者为用户提供不同的选项,收集调试信息等。只是尽量保持简单,这样你就不需要第二个看门狗来观看第一个。< / p>
答案 4 :(得分:-2)
您可能必须保留一个开始的进程列表,并在退出程序时逐个删除它们。我不确定在C ++中这样做的具体细节,但它应该不难。困难的部分可能是确保在应用程序崩溃的情况下关闭子进程。 .Net能够添加一个在发生未处理的异常时调用的函数。我不确定C ++是否提供相同的功能。
答案 5 :(得分:-2)
您可以将每个进程封装在C ++对象中,并在全局范围内保留它们的列表。析构函数可以关闭每个进程。如果程序正常退出但它崩溃了,所有投注都会关闭,那将会正常工作。
这是一个粗略的例子:
class myprocess
{
public:
myprocess(HANDLE hProcess)
: _hProcess(hProcess)
{ }
~myprocess()
{
TerminateProcess(_hProcess, 0);
}
private:
HANDLE _hProcess;
};
std::list<myprocess> allprocesses;
然后每当你启动一个,调用allprocessess.push_back(hProcess);
答案 6 :(得分:-4)
刚刚出头: