检测进程是不是仍在运行
Posted
技术标签:
【中文标题】检测进程是不是仍在运行【英文标题】:Detecting if a process is still running检测进程是否仍在运行 【发布时间】:2009-08-06 11:45:53 【问题描述】:我需要检查具有给定 HANDLE 的进程是否仍在运行,我尝试使用以下代码执行此操作,但它总是在第二次返回 false 时返回,即使进程正在运行。
bool isProcessRunning(HANDLE process)
if(process == INVALID_HANDLE_VALUE)return false;
DWORD exitCode;
if(GetExitCodeProcess(process, &exitCode) != 0)
return false;//always returns here
return GetLastError() == STILL_ACTIVE;//still running
【问题讨论】:
【参考方案1】:您可以通过使用来测试过程寿命
bool isProcessRunning(HANDLE process)
return WaitForSingleObject( process, 0 ) == WAIT_TIMEOUT;
【讨论】:
只需要添加对 INVALID_HANDLE_VALUE 的检查,因为它报告进程正在运行,但它甚至无效:) 如果您打开了进程句柄,即使它已终止,WaitForSingleObject 之类的 API 也不应该返回 INVALID_HANDLE_VALUE。句柄和基础对象必须保持打开状态,直到被引用进程显式关闭(或这些进程被终止)。你确定你不是试图在进程 ID 而不是句柄上调用它吗? 我的意思是在 WaitForSingleObject 之前进行检查,以防进程尚未创建,因此句柄仍处于我将其初始化为的值,即 INVALID_HANDLE_VALUE,因为始终将 INVALID_HANDLE_VALUE 传递给 WaitForSingleObject超时(即 INVALID_HANDLE_VALUE 似乎从未处于信号状态)。【参考方案2】:http://msdn.microsoft.com/en-us/library/ms683189%28VS.85%29.aspx
返回值
如果函数成功,则返回 值非零。
如果函数 失败,返回值为零。到 获取扩展错误信息,调用 GetLastError.
【讨论】:
这不是答案。【参考方案3】:我知道这有点晚了,但是如果您想要获得预期的结果,您的代码应该是这样的。
bool isProcessRunning(HANDLE process)
DWORD exitCodeOut;
// GetExitCodeProcess returns zero on failure
if( GetExitCodeProcess( process, &exitCodeOut ) == 0 )
// Optionally get the error
// DWORD error = GetLastError();
return false;
// Return if the process is still active
return exitCodeOut == STILL_ACTIVE;
如果您只有进程 ID (PID),此 sn-p 将起作用(无错误检查):
bool isProcessRunning(DWORD processID)
if( HANDLE process = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processID ) )
DWORD exitCodeOut;
// GetExitCodeProcess returns zero on failure
if( GetExitCodeProcess( process, &exitCodeOut ) != 0 )
// Return if the process is still active
return exitCodeOut == STILL_ACTIVE;
return false;
【讨论】:
应该避免这种方法,因为可能会为已退出的进程获取 STILL_ACTIVE。 (这是一个有效的退出代码。) @HarryJohnston 当且仅当进程使用 259 作为退出代码,对吗? Microsoft 建议不要将其用作错误代码。由于我正在检查的过程没有机会返回 259(正如我所写的那样),因此退出代码的使用是完全可以接受的。这似乎是一个妖怪,仅当您检查您无权控制的进程的退出代码时才适用。 (不过,了解并意识到这一点是件好事) 在那种特定情况下,这种方法可能是可以接受的。但是,OP 没有说明他们正在检查的过程是否是他们自己的代码,而且您的回答也没有说明这是一项要求。 ... 就个人而言,考虑到使用 WaitForSingleObject 是多么容易,我只是看不到使用 GetExitCodeProcess 的任何优势。当您可以通过使用 WaitForSingleObject 以简单的方式消除风险时,或者通过检查子程序的每个可能的退出路径(包括您可能正在使用的任何第三方库)来以困难的方式消除风险,那么,为什么要采用艰难的方式呢? :-) 刚刚尝试使用WaitForSingleObject
,即使进程仍在运行,它也会返回WAIT_TIMEOUT,可能是因为我们正在使用QSharedMemory
,它锁定了进程接收事件(它已经在等待,基本上) .因此,在我们的特定用例中无法使用WaitForSingleObject(p, 0)
。有好处:-) 我最初实现该功能时可能遇到过这个问题,但忘记了为什么选择GetExitCodeProcess
的细节。总而言之,这是一个有用的练习,希望它对未来的人有所帮助。【参考方案4】:
您可以使用EnumProcesses()
让所有进程在 Windows 上运行。
比如:
bool IsProcessRunning(int pid)
unsigned long processes[2048];
unsigned long num_proc = 0;
unsigned long needed = 0;
// assume that 2048 processes are enought
if (EnumProcesses(processes, sizeof(processes), &needed))
num_proc = needed / sizeof(DWORD);
for (int i = 0; i < num_proc; i++)
if (processes[i] == pid)
return true;
return false;
【讨论】:
@gimpf 不管它有多复杂,它仍然可能有用。 虽然效率很低,而且由于它使用进程 ID 而不是句柄,因此受制于固有的竞争条件。 可能有用,我猜,但可能只在边缘情况下。以上是关于检测进程是不是仍在运行的主要内容,如果未能解决你的问题,请参考以下文章