views:

361

answers:

2

I have a program which runs an external, command line utility and reads the standard output (a PNG image.) Originally during testing, I had the command line program write the image to a temporary file, and then loaded the file into the program. I had a handler for Process.Exited which threw an exception if the exit code was nonzero. I called WaitForExit before loading the temporary image to make sure that the process was finished. If an exception was raised, it was handled in the code which read the temporary image file. Now, I make the call to create the image file directly after calling Process.Start, which works fine if there is no error. If the external program exits abnormally, the exception thrown by the exit handler is no longer caught by my code. If I call WaitForExit before I read the standard output, the program hangs. Is there any way to catch the exception thrown by the exit handler without calling WaitForExit?

A: 

Sounds to me like you command line utility program is not exiting properly. Have you checked this by showing the process window to see if it is doing something incorrect?

My secoud bet would be that not reading the standard output is causing the program not to exit (it is waiting to be able to clear it's output), therefore you must read the standard output first, then wait for the utility to stop.

Thies
I know that it exits unexpectedly (the handler for Process.Exited sees a nonzero exit code and throws an exception.) The problem is that I can't catch the exception thrown by the handler.
pschorf
@pschorf, ahh - I understand. Could you not just store the exception in the Process.Exited handler into a variable and use that - for example throwing it after waiting for the process to exit?
Thies
A: 

The Process.Exited handler is executing in a context which is separate from the function which starts the process. You can fix this two ways.

  1. Write a loop after you start the process. (Using the process' handle, call WaitOne(100) within a loop. If you get an exception, the handle is gone and you should act like the process has finished. If you don't get an exception, the result of true indicates that the process has closed.)
  2. Create an ManualResetEvent that you Reset() before starting the process. After starting the process, call WaitOne() on that event. In the Process.Exited handler, Set() that event, and then the main method will continue on.
John Fisher
I tried to implement the second suggestion you had. It blocked the thread properly, but the exception was still not handled by the try...catch block where i called process.start and waitone.Could you explain the first suggestion further?
pschorf
If you want to catch the exception from the calling code, you would need to store the exception itself in a shared variable. Then the event that you Set() would simply tell the main thread's code to check the exception variable. If it's null, keep going; if it's not null, throw it.
John Fisher