Redirecting Standard Handles – C#

October 16, 2014 - .NET, C#, Programming

Console applications are fairly common for handling simple, routine tasks; sometimes the task is straightforward and otherwise runs on it’s own with little to no user input. Sometimes it has to generate a lot of output that isn’t really necessary. But inevitably, we find we want to launch one of those Console applications from a Windows program, and in order to integrate well into your program you figure you should do something other than just have the program appear in a console window. Enter Standard handle redirection.

Launching a Process in C# is fairly straightforward:

This is just one way to do it; another common approach is to create the ProcessStartInfo structure and use that as part of Process.Start(); this won’t give you the process object until it launches though- that can be troublesome, particularly if you decide you want to standard output, input, or error streams.

There are a few different approaches to redirecting the standard handles from within the .NET Framework. You can set the RedirectStandardOutput, RedirectStandardInput, and RedirectStandardError properties of the ProcessStartInfo to true, and then manipulate the StandardOutput, StandardInput, and StandardError Streams yourself. This can make for very complex code if you want a responsive design. A better alternative is actually built into the Process class itself- and that is to actually use an event-based approach and have an event fire when and only when one of your redirected output streams has output. There are a few gotchas in this approach that can trip you up if you aren’t careful though. the appropriate ProcessStartInfo setting, RedirectStandard* Property should be set to true; UseShellExecute should be false, and “EnableRaisingEvents” on the process should be set to true. Connect event handlers to OutputDataReceived or ErrorDataReceived, Start the program, and then Begin asynchronous reading of the Output and Error streams with BeginOutputReadLine and BeginErrorReadLine. The events you setup will fire, and e.Data will, for example, contain the line of text that was output. Here is a quick example:

With this you can fairly easily redirect the output and error from a command line (or any other) program, and do with it what you like. You could even parse each output line and present standard input to “emulate” a user running the program. This could be useful for test harnesses as well as for when you use a command line tool but would rather that not be made prevalent- the command line program can be run hidden and you can parse and interpret the standard output as needed to update your UI. (this is in some part how many Linux GUI applications function)

Have something to say about this post? Comment!