Wednesday, September 20, 2006

System.Diagnostics.Process and asychronous output

The project I'm working on requires interaction with a command-line executable. We have essentially created an ADO.NET data provider on top of this command-line application that retrieves data for us from a proprietary source.

This ends up working quite well except for one problem. The command-line app sometimes pops up a dialog when it encounters an error. On a desktop environment that's not a problem as the user can just hit the "Ok" button on the dialog. However, in a server environment this is disastrous (especially when we're talking about a Windows Service that cannot interact with the desktop).

Our solution was to use the System.Diagnostic.Process objects asynchronous facilities (subscribing to the OutputDataReceived event and then calling BeginOutputReadLine()) to collect output asynchronously and then have a timer that could kill the request if the command-line app didn't return within a specified interval.

Again, this seemed to work well....until we found out that when we blocked on the WaitForExit() call we could return before all output had been received in our event handler.

To work around this you need to pay attention to the OutputDataReceived event's argument object. The DataReceivedEventArgs object has a Data property that contains the data being delivered for the current event. When that property is null (Nothing in VB.NET) the process has finished.

In our class we simply blocked on a boolean flag until the Data property was null at which point we flipped the flag to true and we knew we could return the data we'd collected.

No comments: