我正在开发的函数的最初目标是,简单地检查一个进程在Windows中是否仍然存在(没有终止,完全运行),给出了一个特定的进程ID。然而,我遇到了一种奇怪的情况:OpenProcess()返回ERROR_ACCESS_DENIED (代码:5),尽管进程资源管理器上没有显示这样的进程。
于是我搜索了一下,发现了一个类似的问题,它分享了一些关于我在寻找什么的想法。
Can OpenProcess with error code ERROR_ACCESS_DENIED be used to know if process exists?
我能够识别出这个问题,但由于解决方案在处理流程的ERROR_ACCESS_DENIED方面并没有多少光明。
总之,我有一些想法是不可能的。这是我到目前为止得到的代码
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, dwPid);
if( hProcess == NULL )
{
dwLastError = GetLastError();
if( dwLastError == ERROR_ACCESS_DENIED )
{
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 processEntry;
processEntry.dwSize = sizeof(PROCESSENTRY32);
if (Process32First(hSnap, &processEntry))
{
while( Process32Next(hSnap, &processEntry) )
{
if (processEntry.th32ProcessID == dwPid)
{
bAliveProcess = TRUE;
break;
}
}
}
CloseHandle(hSnap);
}
}
else
{
BOOL bExit = GetExitCodeProcess(hProcess, &dwExitCode);
if (dwExitCode == STILL_ACTIVE)
{
bAliveProcess = TRUE;
}
CloseHandle(hProcess);
}有了上面的代码,我就能够过滤掉我前面描述的问题。但我只是觉得迭代整个流程列表似乎是一个很大的开销,如果它经常被调用的话。是否有更好的方法来处理这类问题?任何见解都将不胜感激。提前谢谢。
编辑:我知道有一种情况是,进程没有运行,但是它的对象仍然存在(这种情况可能是,调用方没有关闭进程句柄)。我不想将这样的情况计算为存在的进程,因为它们实际上并不在运行。这就是为什么我将GetExitCodeProcess()用于我拥有访问权限的进程,而tl32Snapshot用于我没有的进程。我的假设是错误的吗?
发布于 2019-10-01 08:56:11
会有更好的方法来解决这类问题吗?
的确如此。
使用PID检查进程是否处于活动状态的不是解决方案,因此您应该回去检查您的总体设计。
只需使用启动进程时获得的句柄:
HANDLE hProcess = CreateProcess(...
听起来好像这个过程不是从这个过程中创建的,所以也许可以像您做一次那样获得它,并保留它(即。在找到进程后尝试存储句柄,而不是继续使用PID)。
现在您可以使用例如函数GetExitCodeProcess ala进行检查。:
DWORD returnCode{};
if (GetExitCodeProcess(handle, &returnCode)) {
if (returnCode != STILL_ACTIVE) {
//no longer active使用PID的原因有两个:操作系统可能会将进程保持在死区一段时间,而PID一旦检查就可能被重新用于新进程(在任何正常情况下,您都无法控制它)。
至于ERROR_ACCESS_DENIED:检查进程是否存在根本就不是一个可靠的方法。
https://stackoverflow.com/questions/58178651
复制相似问题