The correct way to handle standard error and output from a program when spawned through the Process class from C #?

I read the documentation for Process.StandardOutput which has this quote in it:

A blocking condition may occur if the parent process calls p.WaitForExit before p.StandardOutput.ReadToEnd, and the child process writes enough text to fill the redirected stream.

So I'm interested. What is the correct way to do this if I also fear that a StandardError might be populated in some scenarios?

Should I use a loop to alternate between reading from standard output and error to avoid either populating or simple enough code:

string error = proc.StandardError.ReadToEnd(); string output = proc.StandardOutput.ReadToEnd(); bool didFinish = proc.WaitForExit(60000); 

Edited after posting multiple answers

So is this the right approach?

 var output = new StringBuilder(); proc.OutputDataReceived += (s, e) => output.Append(e.Data); proc.BeginOutputReadLine(); string error = proc.StandardError.ReadToEnd(); bool didFinish = proc.WaitForExit(60000); 

And then I use the contents of stringbuilder only if the process is complete.

Is this the right approach?

+7
subprocess process
source share
2 answers

Your sample code may lead to a deadlock situation when something was written in StandardOutput , not StandardError . The following example from your related documentation contains the same amount.

Essentially, I would recommend using asynchronous reads in both streams to fill the buffer when streams are being written, and then call WaitForExit .

+6
source share

The problem arises because the child process writes its standard output and standard error to a pair of tubes to which the OS provides the final buffer. If the parent does not actively read both of them, then they can be replenished. When the pipe is full, any subsequent recording on it is blocked.

In your example, you read all StandardError and then all StandardOutput . This works fine if the child process writes only some data to StandardError and / or StandardOutput . This is a problem if the child process wants to write a lot of data to StandardOutput . While the parent process is waiting for data from StandardError , the child process is busy filling the StandardOutput buffer.

The safest way is to read the standard and standard error at the same time. There are several ways to do this:

  • Create separate threads and call ReadToEnd for each
  • Use BeginRead and EndRead in the same thread
  • Add Process.ErrorDataReceived and Process.OutputDataReceived event handlers, then call Process.BeginErrorReadLine and Process.BeginOutputReadLine .
+3
source share

All Articles