Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I determine if a process is associated with a System.Diagnostics.Process object?

Tags:

c#

process

Given a particular System.Diagnostics.Process that has been assigned values to its properties .FileName and .Arguments, what is the best way to determine if it:

  1. has ever been issued a .Start() command or
  2. is currently associated with a process at all?

If .Start() was never issued, then calling .CloseMainWindow() causes an InvalidOperationException, which I'd like to avoid.

like image 443
JYelton Avatar asked Nov 05 '22 13:11

JYelton


2 Answers

If you're closing a process by calling .CloseMainWindow(), wrapping the call in a try/catch block is the correct thing to do.

Do this:

try
{
    process.CloseMainWindow()
}
catch (InvalidOperationException)
{
    // purposely do nothing here - the process exited before we told it to.
}

This is because checking the process properties before shutting the process down creates a race condition: both the property check and the call to .CloseMainWindow() are racing to see which can complete first.

Consider this series of events:

  1. The process is running
  2. Your code calls process.HasExited and receives false
  3. The process exits of its own accord, as it's finished
  4. Since step 2 returned false, your code calls process.CloseMainWindow(), and gets an InvalidOperationException: Process has exited, so the requested information is not available.

No amount of speeding up your code, nor using locks, nor any other strategy can guarantee that the process won't exit after your if statement. There is always the race condition. So instead, use try/catch.

If you need to keep track of whether the process has ever been launched, you may want to wrap the process in your own class. You can use a lock when launching the process and set a boolean flag to indicate that it has been launched.

class ProcessWrapper
{
    public HasStarted;
    public ProcessWrapper(Process p, ProcessStartInfo psi)
    {
        // do argument and filename validation etc. here
        lock(HasStarted)
        {
            p.Start(psi);
            HasStarted = true;
        }
    }
}
like image 67
culix Avatar answered Nov 15 '22 10:11

culix


Have you tried checking Process.Id and one of the Exit properties ?

Ref.

In response to poster's comments: perhaps you will have to wrap in a try/catch and an exception being thrown indicates not started? It's not pretty!

like image 31
Mitch Wheat Avatar answered Nov 15 '22 10:11

Mitch Wheat