This should be easier. .NET provides some great ways to launch a console application and capture it's output, but I kept finding bad example after bad example and ended up running around like a chicken with my head cut off. Hence, this post.
To clarify what I mean by "redirecting console output", most of us have seen a typical console window:
This is what it usually looks like when you run a console application in Windows. However, while working on a side project of mine, I needed a way to integrate CDRDAO into my application. CDRDAO is an open-source console application that burns and rips CDs; I wanted to integrate it without popping up the ugly black console window, and I also needed to be able to read its output within my application. I wanted it to look something like this:
Easy, I thought. Well, sort of, but not exactly straightforward without some research.
Running a Process
Usually when starting a process, you would simply use the quick and easy
Process.Start static method. However, in order to allow for more complicated operations, you'll need to instantiate the
Process classes like so:
Hiding the Window
Hiding the window is as simple as setting the
CreateNoWindow property of the
ProcessStartInfo class to
true. Don't take a wild guess like I did and try to set the
WindowStyle property to
ProcessWindowStyle.Hidden, as it appears to do nothing at all.
This is where it gets a tad bit more complicated, as there are numerous things you must do to make the output redirections work. Let's just lay down the code and then we can walk through it:
The first new thing we've added here is
info.UseShellExecute = false;. By default, the
Process class uses the system shell to execute processes. Several things are affected by this, but most important is that you cannot redirect output when using the system shell. However, when not using the system shell (setting
false), you must provide the full, rooted path to the EXE file, as the current working directory does not apply.
Next we have
info.RedirectStandardOutput = true;, which simply tells the process that we want to redirect the output to our application. We also need to enable raising events on the
Process class, and hook up an event handler to the
OutputDataReceived event. This new
process_OutputDataReceived event handler will allow us to do whatever we want with the output from the CDRDAO process.
Furthermore, we set the
SynchronizingObject property to the instance of our class.
You'd think you'd be done here, but after all that in my testing with CDRDAO, I wasn't getting any output in my
process_OutputDataReceived event. It turns out that CDRDAO happens to output all its messages as standard errors, instead of standard output. Therefore, it's a good idea to (and you might need to) redirect/capture the standard error output as well:
The three new lines added here should be fairly obvious, as they follow the same logic as the standard output:
RedirectStandardError which tells the process to redirect the output,
ErrorDataReceived which hooks up the event, and
BeginErrorReadLine which initializes capturing the error output.
Consuming the Output
Obviously, there are a number of things you can do in the
process_OutputDataReceived events, such as parsing the output to control the logic of your application, or simply showing the output to the user. It's also important to note that you can combine those two event handlers into one without issues, and just point both
ErrorDataReceived to the same event handler method.
Then, in a Windows Forms application, you can send your output to a
TextBox control to display it nicely. It works best if you do it like this:
Here, we simply check to make sure
null and that the form isn't disposed, as otherwise if the user closes the form before the process has exited, bad things will happen.
Finally, it's important to use the
AppendText method of the
TextBox control for performance reasons. The method will also automatically scroll to the end with each append operation.
Let us know in the comments if you run into any issues or do anything worth bragging about.