假设我运行一个应用程序,一段时间后,这个应用程序将被用户closures。 有没有可能找出程序何时退出? 当我运行该应用程序时,我可以得到它的进程ID吗?
这是从这里引述:
#include <windows.h> #include <stdio.h> #include <tchar.h> #include <conio.h> void _tmain( int argc, TCHAR *argv[] ) { STARTUPINFO si; PROCESS_INFORMATION pi; STARTUPINFO sj; PROCESS_INFORMATION pj; ZeroMemory( &si, sizeof(si) ); si.cb = sizeof(si); ZeroMemory( &pi, sizeof(pi) ); ZeroMemory( &sj, sizeof(sj) ); sj.cb = sizeof(sj); ZeroMemory( &pj, sizeof(pj) ); // Start the child process p1.exe. Make sure p1.exe is in the // same folder as current application. Otherwise write the full path in first argument. if(!CreateProcess(L".\\p1.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &sj, &pj)) { printf( "Hello CreateProcess failed (%d)\n", GetLastError() ); getch(); return; } // Start child process p2.exe. Make sure p2.exe is in the // same folder as current application. Otherwise write the full path in first argument. if(!CreateProcess(L".\\p2.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { printf( "CreateProcess2 failed (%d)\n", GetLastError() ); getch(); return; } // Wait until child processes exit. WaitForSingleObject( pi.hProcess, INFINITE ); WaitForSingleObject( pj.hProcess, INFINITE ); // Close process and thread handles. CloseHandle( pi.hProcess ); CloseHandle( pi.hThread ); CloseHandle( pj.hProcess ); CloseHandle( pj.hThread ); getch(); }
CreateProcess和WaitForSingleObject是实现这一目的的简单方法:从CreateProcess获得进程句柄,然后等待它与WFSO,不要忘记关闭您使用的任何句柄。 但是等等…有一个问题。 问题是,对于GUI进程,这两个进程都可能挂起。 为什么?
出现这个问题的原因是你的应用程序有一个窗口,但不是抽取消息。 如果生成的应用程序使用其中一个广播目标( HWND_BROADCAST
或HWND_TOPMOST
)调用SendMessage,那么SendMessage将不会返回到新应用程序,直到所有应用程序都处理完消息 – 但是您的应用程序无法处理消息,吨泵消息….所以新的应用程序锁定,所以你的等待永远不会成功…. DEADLOCK。
如果你对生成的应用程序有绝对的控制权,那么你可以采取一些措施,例如使用SendMessageTimeout而不是SendMessage(例如,如果有人仍然在使用DDE启动)。 但是有些情况会导致您无法控制的隐式SendMessage广播,例如使用SetSysColors API。
(a)将Wait分解成单独的线程,(b)在Wait上使用超时,并在Wait循环中使用PeekMessage,以确保泵送消息,(c)使用MsgWaitForMultipleObjects API的WaitForSingleObject。
在Windows上,您可以使用WaitForSingleObject来实现此功能。
提供更多控制的另一种方法是使用Win32 Job API,请参阅CreateJobObject()和AssignProcessToJobObject() 。 这将允许您使用SetInformationJobObject()来使用IO完成端口异步地监视产生的进程,它比您需要的更复杂并且可能更多,但它确实使您能够更好地控制产生的进程。
我想提一下,你不必实际创建一个进程,以便能够等待它的终止。 基本上,如果你知道它的PID,你可以这样做:
HANDLE h = OpenProcess(SYNCHRONIZE, TRUE, pid); WaitForSingleObject(h, INFINITE );
完整的例子: https : //gist.github.com/rdp/6b5fc8993089ee12b44d (在这里留下评论,如果你想编译版本可用)。
在谷歌快速搜索,我发现这两个方法从MSDN可以是有用的:
CreateProcess和GetExitCodeProcess 。 这假设你正在你的应用程序中创建一个进程。
您可以执行轮询方法来检查创建的进程状态。 我从来没有做过这样的事情,但对我来说似乎是一个很奇怪的做法。
至少在Windows上,有一些(使用不足的)C运行库功能可用于此。 请参阅C运行时库参考>过程和环境控制 。
具体来说,你有_spawnlp (_P_WAIT, cmdname, arg0, ..., argn, 0)
(“用参数l ist 生成 ,用p ath变量来定位文件”),它在PATH和当前目录中搜索cmdname。 请注意,“遵循argn,必须有一个NULL指针来标记参数列表的末尾。
例如
#include <stdio.h> #include <process.h> int main() { puts("waiting"); _spawnlp(_P_WAIT, "mspaint.exe", "mspaint.exe", 0); puts("returned"); }