2

Attempting to implement a poor man's test of whether a process is still running or not (essentially an equivalent of the trivial kill(pid, 0).)

Hoped to be able to simply call OpenProcess with some minimal desired access then test for either GetLastError() == ERROR_INVALID_PARAMETER or GetExitCodeProcess(...) != STILL_ACTIVE.

Nice try... Running on Windows XP, as administrator:

HANDLE hProc = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (!hProc) {
  DWORD dwLastError = GetLastError();
}

...fails miserably with dwLastError == ERROR_ACCESS_DENIED when pid is owned by a different (not SYSTEM) user. Moreover, if pid was originally owned by a different user but has since terminated, OpenProcess also fails with ERROR_ACCESS_DENIED (not ERROR_INVALID_PARAMETER.)

Do I have to use Process32First/Process32Next or EnumProcesses?

I absolutely do not want to use SeDebugPrivilege.

Thanks, V

vladr
  • 65,483
  • 18
  • 129
  • 130
  • 1
    see also http://stackoverflow.com/questions/1591342/how-to-determine-if-a-windows-process-is-running which may have some other more reliable methods – rogerdpack Sep 28 '12 at 00:17
  • @rogerdpack in this case the only available information is the `pid`. No handle is available. I know about http://stackoverflow.com/questions/1591342/how-to-determine-if-a-windows-process-is-running , I even contributed a comment or two there. :) – vladr Oct 09 '12 at 18:44
  • yes, more I was making the comment to alert users that I'd added an answer that that might work for this question, as well, but didn't want to add it to both places. cheers! – rogerdpack Oct 10 '12 at 21:29

2 Answers2

1

If you have a process ID:

// this should succeed even when a medium integrity process
// requests access to a high integrity process
if (HANDLE h = OpenProcess(SYNCHRONIZE, FALSE, pid))
{
    // do a wait, if the handle is signaled: not running
    DWORD wait = WaitForSingleObject(h, 0);
    if (wait == WAIT_OBJECT_0) return FALSE;
}
// cannot get a handle to the process:
// probably running at system integrity level
// I'm not sure how reliable this check is, but it seems to work:
// if access is denied: running
// if invalid parameter: not running
else if (GetLastError() != ERROR_ACCESS_DENIED) return FALSE;

If you have a window handle that should be valid for as long as the process is running, this is a good alternative:

if (hWnd && !IsWindow(hWnd)) return FALSE;
George Valkov
  • 1,217
  • 12
  • 10
  • Was this fixed after Windows XP? "if `pid` was originally owned by a different user but has since terminated, `OpenProcess` also fails with `ERROR_ACCESS_DENIED` (not `ERROR_INVALID_PARAMETER`.)" – vladr Feb 10 '15 at 00:42
0
static BOOL
isProcessAlive(DWORD th32ProcessID) {
  BOOL bSuccess = FALSE;

  HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  if (hSnap != INVALID_HANDLE_VALUE) {
    PROCESSENTRY32 pe32 = { sizeof(pe32), 0 };
    if (Process32First(hSnap, &pe32)) {
      while (pe32.th32ProcessID != pid && Process32Next(hSnap, &pe32));
      _ASSERT(GetLastError() == 0 || GetLastError() == ERROR_NO_MORE_FILES);
      bSuccess = (pe32.th32ProcessID == th32ProcessID);
    }
    CloseHandle(hSnap);
  }
  return bSuccess;
}
vladr
  • 65,483
  • 18
  • 129
  • 130