正如 marcinj 解释的那样,calc.exe 正在启动第二个进程,然后立即退出。您正在等待HANDLE 到calc.exe 进程,因此当calc.exe 退出时,等待得到满足。
如果您想等到所有(大)子进程结束,您需要将calc.exe 进程包装在Job object 中。
调用CreateJobObject(),将calc.exe进程的HANDLE传递给AssignProcessToJobObject(),然后等待来自作业对象的通知(仅仅等待作业本身是行不通的,见How do I wait until all processes in a job have exited?解释原因)。
calc.exe 启动的任何新进程,以及它们启动的进程等等,都将自动添加到同一个作业中(除非它们通过 @ 的 CREATE_BREAKAWAY_FROM_JOB 标志明确请求不添加到作业中) 987654336@,但在这个例子中我们不用担心)。当作业通知您所有进程都已结束时,您可以停止等待进一步的通知。
例如:
#include <windows.h>
#include <iostream>
#include <string>
using namespace std;
int main()
{
HANDLE Job = CreateJobObject(NULL, NULL);
if (!Job)
{
std::cout << "CreateJobObject, error " << GetLastError() << "\n";
return 0;
}
HANDLE IOPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
if (!IOPort)
{
std::cout << "CreateIoCompletionPort, error " << GetLastError() << "\n";
CloseHandle(Job);
return 0;
}
JOBOBJECT_ASSOCIATE_COMPLETION_PORT Port;
Port.CompletionKey = Job;
Port.CompletionPort = IOPort;
if (!SetInformationJobObject(Job, JobObjectAssociateCompletionPortInformation, &Port, sizeof(Port)))
{
std::cout << "SetInformation, error " << GetLastError() << "\n";
CloseHandle(IOPort);
CloseHandle(Job);
return 0;
}
STARTUPINFO si = { sizeof(STARTUPINFO) };
PROCESS_INFORMATION pi = {};
WCHAR cmdline[] = L"calc.exe";
if (!CreateProcessW(NULL, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
std::cout << "CreateProcess, error " << GetLastError() << "\n";
CloseHandle(IOPort);
CloseHandle(Job);
return 0;
}
if (!AssignProcessToJobObject(Job, pi.hProcess))
{
std::cout << "Assign, error " << GetLastError() << "\n";
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(IOPort);
CloseHandle(Job);
return 0;
}
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
DWORD CompletionCode;
ULONG_PTR CompletionKey;
LPOVERLAPPED Overlapped;
while (GetQueuedCompletionStatus(IOPort, &CompletionCode, &CompletionKey, &Overlapped, INFINITE))
{
if ((reinterpret_cast<HANDLE>(CompletionKey) == Job) &&
(CompletionCode == JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO))
{
break;
}
}
CloseHandle(IOPort);
CloseHandle(Job);
std::cout << "hi! Im done!";
return 0;
}