Redirect Console Output in C#

Those of you that know me know that I love a good console application. I use them all the time for samples and prototypes. Sometimes it’s nice to capture the output from a console application to share with others.

It’s remarkably simple to accomplish this with the .NET Framework. There is a static method Console.SetOut that accepts a TextWriter. Redirecting output from your console application is as simple as creating a TextWriter and calling that method.

Here’s a quick example (taken directly from MSDN):

Console.WriteLine("Hello World");
FileStream fs = new FileStream("Test.txt", FileMode.Create);
// First, save the standard output.
TextWriter tmp = Console.Out;
StreamWriter sw = new StreamWriter(fs);
Console.SetOut(sw);
Console.WriteLine("Hello file");
Console.SetOut(tmp);
Console.WriteLine("Hello World");
sw.Close();

The Almighty Console Application

When I was learning C++ in college, I couldn’t wait to start developing applications that were more than just a console app. It was the twenty-first century, and “real” applications had forms with stuff you could click with a mouse. Nobody wants an app that you can only interact with by typing. And no graphics? No thanks.

It’s funny how time can change you.

I still believe that, generally, people don’t want a console application. And if I’m writing an application intended to be used by others, I’m probably going to go with Windows Forms, ASP.net, or WPF. I do a significant amount of development that isn’t aimed at end users, though, and that’s where I’ve learned to appreciate the value of the console application.

Your first try will likely be your worst

The first time you try something new, it’s likely to be your worst attempt. So, if you’re experimenting with a new technology or implementing logic that you aren’t familiar with, why would you try in production code? Further, once you’ve got it implemented and functional in your production code, there’s a chance that some unnecessary figuring-it-out code will sneak into the product.

This is where the oft overlooked console application comes into play. For my money, the console app is the fastest way to an isolated, bare-bones sandbox for learning and optimizing a solution. A valid argument can be made that a Windows Forms application is just as fast(er), but you can waste time manipulating controls on a form that really don’t provide any value at the end of the day. Hard-code your input or prompt the user and use Console.ReadLine()–it’s as fast as declaring a variable, and your project doesn’t get any of the extra “fluff” that comes with forms and designers. (It’s also great for blogging since you don’t have to explain what each control is or provide screenshots!)

A personal library

You know how you did that one cool thing for some project a few years ago? Can you send me that code?

A great side-effect of doing your learning and experimenting outside of the application it’s ultimately targeted for is that you build a personal snippet and reference library. If you browse through my Visual Studio projects folder, you’ll see a LOT of folders: EncryptionConsole, ZipConsole, FtpConsole, TfsSdkConsole, SerializationConsole, etc. It’s easy to find a functional, self-contained code sample that you can share with others. Or, if you need to expand on a previous topic with a more advanced technique, you’ve got a foundation already built.

Console Application Proxy

I’m working on a project where it’s necessary to use a client application provided by a third party to query the third party’s system from within my own system. This can be done very easily in .net by simply redirecting standard input and output.

Here is a sample application that demonstrates how:

var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardInput = true;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.FileName = @"WorkApp.exe";
p.Start();

string input;
do
{
    // get request from user
    Console.Write("> ");
    input = Console.ReadLine();
    p.StandardInput.WriteLine(input);

    // get response from console
    var output = p.StandardOutput.ReadLine();
    Console.WriteLine(output);
} while (input != "x");

if (!p.HasExited)
{
    p.Kill();
}