15

I use Process.Kill() to kill a process. Like this:

if( !process.WaitForExit( 5000 ) ) {
   process.Kill();
}

and sometimes the process will exit right in between the lines, so control will get inside if and then Kill will yield an exception:

System.InvalidOperationException
Cannot process request because the process (ProcessIdHere) has exited.
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.Kill()
//my code here

Now wrapping the code into try-catch doesn't seem to be a good idea because InvalidOperationException can be called for other reasons.

Is there a way to kill a process without getting an exception in the described scenario?

sharptooth
  • 167,383
  • 100
  • 513
  • 979

2 Answers2

12

You could P/Invoke TerminateProcess passing it Process.Handle. Then manually evaluating the cause of it (GetLastError()). Which is roughly, what Process.Kill() does internally.

But note that TerminateProcess is asynchronous. So you'd have to wait on the process handle to be sure it is done. Using Process.Kill() does that for your.

Update: Correction, Process.Kill() also runs asynchronously. So you'll have to use WaitForExit() to wait for termination to complete - if you care.

Frankly, I wouldn't bother. Of course there is always the (remote?) chance that some "arbitrary" InvalidOperationExcepion bubbles up out of that line of code, that is not related to the process no longer being there or the Process object to be in an invalid state, but in reality I think you can just go with the try/catch around the Kill.

In addition, depending on your application, you could consider logging this kill anyway, since it seems some sort of last resort measure. In that case log the actual InvalidOperationException with it. If things go strange, you at least have your logs to check why the Kill failed.

Having all that said, you might also want to consider catching / handling Win32Exception for the same reasons.

Christian.K
  • 47,778
  • 10
  • 99
  • 143
6

You need to use HasExited:

if(!process.WaitForExit(5000)) 
{
   if (!process.HasExited)
   {
       process.Kill();
   }
}

See here:

http://msdn.microsoft.com/en-us/library/system.diagnostics.process.hasexited.aspx

Lloyd
  • 29,197
  • 4
  • 84
  • 98
  • 6
    That still has a race condition. `HasExited` may return `false`, but by the time `Kill` executes, the process could be gone - resulting in an `InvalidOperationException` still. – Christian.K Nov 26 '12 at 12:24
  • 1
    We're talking fractions of a nanosecond so that seems unlikely, but if that is the case you can't stop it, best you can do is catch the exception. – Lloyd Nov 26 '12 at 12:25
  • "Fractions of nanoseconds" seems like an exaggeration, to be honest. Your process might get preemted, for example, in between the two calls, heck, the box might even hibernate in between coming back up in an "unfortunate order" ;-) But I agree, that catching the exception is the only "robust" solution - if you care. YMMV of course. – Christian.K Nov 26 '12 at 12:27
  • OK true, I just meant it's a very small chance. It's a small chance non the less and should be handled :) – Lloyd Nov 26 '12 at 12:44