views:

631

answers:

7

This is concerning Windows XP processes.

I have a process running, let's call it Process1. Process1 creates a new process, Process2 and saves its id.

Now, at some point Process1 wants Process2 to do something, so it first needs to make sure that process2 is still alive and that the user has not not killed it.

How can I check that this process is still running? Since I created it, I have the Process ID, I would think there is some library function along the lines of IsProcessIDValid( id ) but I can't find it on MSDN

+3  A: 

You can never check and see if a process is running, you can only check to see if a process was running at some point in the recent past. A process is an entity that is not controlled by your application and can exit at any moment in time. There is no way to guaranteed that a process will not exit in between the check to see if it's running and the corresponding action.

The best approach is to just do the action required and catch the exception that would be thrown if the process was not running.

JaredPar
@Michael, the intent here is clear. The OP specifically said they wanted to check to see if Process2 was alive so they could do something with it.
JaredPar
Another issue is that PIDs can be re-used quickly. So if Process 2 dies, and the PID is recycled, you might think your process is still running when it isn't.
Adrian McCarthy
+5  A: 

The process handle will be signaled if it exits.

So the following will work (error handling removed for brevity):

BOOL IsProcessRunning(DWORD pid)
{
    HANDLE process = OpenProcess(SYNCHRONIZE, FALSE, pid);
    DWORD ret = WaitForSingleObject(process, 0);
    CloseHandle(process);
    return ret == WAIT_TIMEOUT;
}

Note that process ID's can be recycled - it's better to cache the handle that is returned from the CreateProcess call.

You can also use the threadpool API's (SetThreadpoolWait on Vista+, RegisterWaitForSingleObject on older platforms) to receive a callback when the process exits.

EDIT: I missed the "want to do something to the process" part of the original question. You can use this technique if it is ok to have potentially stale data for some small window or if you want to fail an operation without even attempting it. You will still have to handle the case where the action fails because the process has exited.

Michael
This should be titled WasProcessRunning, it's a misnomer to call it IsProcessRunning
JaredPar
WasProcessRunning is such a sloppy name. Reversing the test at the end and changing the name to "HasProcessExited" would be better.
Michael
+3  A: 

You can use GetExitCodeProcess. It will return STILL_ACTIVE (259) if the process is still running (or if it happened to exit with that exit code :( ).

Dolphin
+1  A: 

call EnumProcesses() and check if the PID is in the list.

http://msdn.microsoft.com/en-us/library/ms682629%28VS.85%29.aspx

Lance Rushing
If process 2 is dead, the PID can be recycled.
Adrian McCarthy
+1  A: 

JaredPar is right in that you can't know if the process is running. You can only know if the process was running at the moment you checked. It might have died in the mean time.

You also have to be aware the PIDs can be recycled pretty quickly. So just because there's a process out there with your PID, it doesn't mean that it's your process.

Have the processes share a GUID. (Process 1 could generate the GUID and pass it to Process 2 on the command line.) Process 2 should create a named mutex with that GUID. When Process 1 wants to check, it can do a WaitForSingleObject on the mutex with a 0 timeout. If Process 2 is gone, the return code will tell you that the mutex was abandoned, otherwise you'll get a timeout.

Adrian McCarthy
A: 

Another way of monitoring a child-process is to create a worker thread that will :

  1. call CreateProcess()
  2. call WaitForSingleObject() // the worker thread will now wait till the child-process finishes execution. it's possible to grab the return code (from the main() function) too.
Maciek
A: 

DCOM already does all of this stuff for free, why are you reinventing the wheel?

Paul Betts