So many mistakes for me to make, so little time...capturing StandardError and StandardOutput
This struck me as particularly interesting, because it's one of those "doh!" things that is simultaneously completely obvious after the fact but not obvious on a cursory glance if you're not paying attention.
If, in C#/.NET, you wish to spawn a process of CMD.EXE /C SomeBatchFileOrSomeProgram.exe, and you wish to capture both the StandardOutput and the StandardError, well, you need to think.
If you do something like this:
Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardError = true; p.StartInfo.FileName = "test.exe"; p.Start(); string output = p.StandardError.ReadToEnd(); p.WaitForExit();
You'll only get StandardError. But of course, if you try to ReadToEnd both streams (here's where it's obvious) the first one will of course block if standard error output occurs, since you can't read from standard error until you're done with standard output, etc etc, blah blah, well you get it.
string output = p.StandardOutput.ReadToEnd(); string error = p.StandardError.ReadToEnd(); p.WaitForExit();
There are lots of code samples around that contain this bug. Of course, the bug won't happen if your spawned console process doesn't mix standard error and standard output. But, when you spawn a batch file, certainly it will spawn other processes and who knows.
This fellow at CodeProject has the right idea, although his sample wasn't created to solve this problem, but rather another.
Process Proc = Process.Start(Info);
m_StdOutReader = new RedirOutReader(Proc, Printer, Proc.StandardOutput);
m_StdErrReader = new RedirOutReader(Proc, Printer, Proc.StandardError);
He spawns two threads, one to handle standard error and one to handle standard output, which is the alluded-to-and-recommended-but-no-one-wrote-the-sample-cause-it-would-have-been-too-hard solution to this problem.