假设我运行一个应用程序,一段时间后该应用程序将被用户关闭。是否有可能找出程序何时退出?我可以在运行该应用程序时获取它的进程ID吗?
答案 0 :(得分:9)
这是here的引用:
#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();
}
答案 1 :(得分:2)
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。
答案 2 :(得分:1)
在Windows上,您可以使用WaitForSingleObject来实现此功能。
答案 3 :(得分:1)
提供更多控制的另一种方法是使用Win32 Job API,请参阅CreateJobObject()和AssignProcessToJobObject()。这将允许您使用SetInformationJobObject()使用IO完成端口异步监视生成的进程,它更复杂,可能比您需要的更多,但它确实可以让您更好地控制生成的进程。
答案 4 :(得分:1)
我想提一下,您不必实际创建流程,以便能够等待其终止。基本上,如果你知道它的PID,你可以这样做:
HANDLE h = OpenProcess(SYNCHRONIZE, TRUE, pid);
WaitForSingleObject(h, INFINITE );
完整示例:https://gist.github.com/rdp/6b5fc8993089ee12b44d(如果您希望编译版本可用,请在此留言。)
答案 5 :(得分:0)
在谷歌的快速搜索中,我发现msdn中的这两种方法很有用:
CreateProcess和GetExitCodeProcess。假设您在应用程序中创建了一个流程。
您可以执行轮询方法来检查创建的进程状态。我从来没有做过这种事,但对我来说似乎是一种非常奇怪的方法。
答案 6 :(得分:0)
至少在Windows上,有一些(未充分利用?)C运行时库功能可用于此。 请参阅C Run-Time Library Reference > Process and Environment Control。
具体来说,您有_spawnlp (_P_WAIT, cmdname, arg0, ..., argn, 0)
(“ spawn 且参数 l ist,使用 p ath变量找到文件“),它在PATH和当前目录中搜索cmdname。
请注意,“在argn之后,必须有一个NULL指针来标记参数列表的结尾。”
E.g。
#include <stdio.h>
#include <process.h>
int main() {
puts("waiting");
_spawnlp(_P_WAIT, "mspaint.exe", "mspaint.exe", 0);
puts("returned");
}