为什么当进程ID不再运行时OpenProcess()返回非0值
我开始使用其他应用程序的新实例,CreateProcess从实例和我结束了保存PID,这样我可以在以后检查如果进程仍在运行。
我正在使用以下方法来检查它是否正在运行:
procedure TfrmRSM.Button1Click(Sender: TObject);
begin
var
ahandle := OpenProcess(PROCESS_ALL_ACCESS, true, aPID);
if ahandle = 0 then
ShowMessage('is not running')
else
ShowMessage('is running');
CloseHandle(ahandle);
end;
0当进程不再运行时,上面的代码应该返回,但它仍然返回一个大于0
使用 CreateProcess 后我正在关闭句柄
如果我使用的方法不正确,有什么正确的方法可以检查 PID 是否正在运行?我只能找到使用应用程序名称的方法。
回答
我正在使用 Example 中的 CreateProcess 启动另一个应用程序的新实例,我最终保存了 PID,以便以后可以检查该进程是否仍在运行。
以正确的操作方法是保持开放的HANDLE是CreateProcess()给你,然后你就可以通过查询它WaitForSingleObject()或者GetExitCodeProcess()看看是否进程已终止或没有,然后关闭HANDLE,当你不再需要它。
在评论中,您提到您的启动应用程序可能会终止并与目标进程分开重新启动。在这种情况下,HANDLE如果您仍然打开它,您可以关闭它,将其 PID 和创建日期/时间保存在您可以从中取回的地方,然后当您的应用程序重新启动时,它可以枚举正在运行的进程(或者)以查看目标是否EXE 仍在运行并且具有匹配的 PID 和日期/时间,如果是,则为HANDLE该 PID打开一个新的。请小心,因为这确实会引入一个小的竞争条件,目标进程可能会在您检测到它的存在后终止,并且它的 PID 可能会在您有机会打开它之前被回收。因此,您可能需要HANDLE在打开后再次重新验证的信息。
否则,你的应用程序的关闭(甚至之前)期间,您可以卸载的开放HANDLE从CreateProcess()一个单独的助手进程在后台监视正在运行的停留HANDLE,然后你的主应用程序可以得到HANDLE重新启动之后,从该助手回来。或者,CreateProcess()首先在 helper 中执行实际调用,以便HANDLE监控始终保持在单个进程中,并让您的主应用程序在需要时查询 helper 的状态。
我正在使用以下方法来检查它是否正在运行:
那是行不通的,因为您不知道 PID 是否仍然有效,甚至不知道您感兴趣的同一个进程。一旦该进程终止,它的 PID 可以随时回收以用于新的过程。
当进程不再运行时,上面的代码应该返回 0 但它仍然返回一个大于 0 的数字
OpenProcess()可以返回非零值的唯一方法是指定的 PID 是否实际正在运行。但这并不能保证它与您感兴趣的过程相同。至少,在OpenProcess()返回非零之后HANDLE,您可以查询HANDLE其信息(EXE 文件路径、创建日期/时间等)以查看它是否与您期望的过程相同。如果信息不匹配,则 PID 被回收。
- A way to improve reliability would be to log the StartDate/Time of the process along the PID. And when trying to match the PID to a running process, check if GetProcessTimes return values coherent with the StartDate/Time originally logged.