我正在尝试重新实现 .NET 的 Process.Exited
事件,但到目前为止我一直没有成功。应用程序未打开未返回任何错误。我错过了什么?
#include <stdio.h>
#include <windows.h>
static void CALLBACK OnExited(void* context, BOOLEAN isTimeOut);
int main()
{
char *cmd = "C:\\Windows\\System32\\notepad.exe";
STARTUPINFOA si = { sizeof(STARTUPINFOA) };
//si.cb = STARTUPINFOA.sizeof;
PROCESS_INFORMATION pi;
if(CreateProcessA(NULL, cmd, NULL, NULL, FALSE, DETACHED_PROCESS | CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
HANDLE hWait;
if(!RegisterWaitForSingleObject(&hWait, pi.hProcess, OnExited, NULL, INFINITE, WT_EXECUTEONLYONCE))
{
printf("register failed! = %d", GetLastError());
}
}
else
{
printf("error = %d\n", GetLastError());
}
}
static void CALLBACK OnExited(void* context, BOOLEAN isTimeOut)
{
printf("OnExited got called!\n");
}
最佳答案
您正在使用 CREATE_SUSPENDED
标志创建新进程,但您没有恢复进程(通过将 pi.hThread
传递给 ResumeThread()
) 注册新进程 HANDLE
后通知。即使您这样做了,您也不会在退出 main()
之前等待通知到达。
您也不会在使用完 pi.hThread
、pi.hProcess
或 hWait
后关闭它们。
尝试更像这样的东西:
#include <stdio.h>
#include <windows.h>
static void CALLBACK OnExited(void* context, BOOLEAN isTimeOut);
int main()
{
char *cmd = "C:\\Windows\\System32\\notepad.exe";
STARTUPINFOA si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
if (!CreateProcessA(NULL, cmd, NULL, NULL, FALSE, DETACHED_PROCESS | CREATE_SUSPENDED, NULL, NULL, &si, &pi))
{
printf("create process error = %u\n", GetLastError());
}
else
{
HANDLE hWait = NULL;
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!hEvent)
{
printf("create event error = %u\n", GetLastError());
}
else if (!RegisterWaitForSingleObject(&hWait, pi.hProcess, OnExited, hEvent, INFINITE, WT_EXECUTEONLYONCE))
{
printf("register wait error = %u\n", GetLastError());
}
ResumeThread(pi.hThread);
CloseHandle(pi.hThread);
if (hEvent)
{
if (hWait)
{
WaitForSingleObject(hEvent, INFINITE);
UnregisterWait(hWait);
}
CloseHandle(hEvent);
}
CloseHandle(pi.hProcess);
}
return 0;
}
static void CALLBACK OnExited(void* context, BOOLEAN isTimeOut)
{
printf("OnExited got called!\n");
SetEvent((HANDLE)context);
}
或者,如果省略 CREATE_SUSPENDED
标志,则可以省略 ResumeThread()
。即使进程在等待线程开始监视它之前结束,等待通知仍然有效,只要您不在等待满足之前关闭进程句柄:
#include <stdio.h>
#include <windows.h>
static void CALLBACK OnExited(void* context, BOOLEAN isTimeOut);
int main()
{
char *cmd = "C:\\Windows\\System32\\notepad.exe";
STARTUPINFOA si = {};
si.cb = sizeof(si);
PROCESS_INFORMATION pi;
if (!CreateProcessA(NULL, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
{
printf("create process error = %u\n", GetLastError());
}
else
{
CloseHandle(pi.hThread);
HANDLE hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!hEvent)
{
printf("create event error = %u\n", GetLastError());
}
else
{
HANDLE hWait = NULL;
if (!RegisterWaitForSingleObject(&hWait, pi.hProcess, OnExited, hEvent, INFINITE, WT_EXECUTEONLYONCE))
{
printf("register wait error = %u\n", GetLastError());
}
else
{
WaitForSingleObject(hEvent, INFINITE);
UnregisterWait(hWait);
}
CloseHandle(hEvent);
}
CloseHandle(pi.hProcess);
}
return 0;
}
static void CALLBACK OnExited(void* context, BOOLEAN isTimeOut)
{
printf("OnExited got called!\n");
SetEvent((HANDLE)context);
}
但是,无论哪种方式,在如此简单的控制台应用程序中使用 RegisterWaitForSingleObject()
都不是很有用。相反,它在多线程/GUI 应用程序中更有意义。对于此示例,您可以只使用 WaitForSingleObject()
代替:
#include <stdio.h>
#include <windows.h>
int main()
{
char *cmd = "C:\\Windows\\System32\\notepad.exe";
STARTUPINFOA si = {};
si.cb = sizeof(STARTUPINFOA);
PROCESS_INFORMATION pi;
if (!CreateProcessA(NULL, cmd, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi))
{
printf("create process error = %d\n", GetLastError());
}
else
{
CloseHandle(pi.hThread);
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
printf("Exited!\n");
}
return 0;
}
关于c++ - 我如何运行一个进程然后在它退出时得到通知?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49161232/