I had the situation today in which I needed to take standard console output and write it to an alternate location. Typically console output gets written to the console window's standard output (i.e. the computer monitor's screen) via the various Write() and WriteLine() methods. In order to change the destination of the output you usually create an instance of a TextWriter, assign it to the Console object (via SetOut(...)), and away you go.
However, all of the examples that I found regarding this technique involved redirecting console output to a stream writer over a FileStream or a MemoryStream so the output wasn't ever visible. That is, the stream was opened, information was pumped into it via the various methods, and when the application ended the stream was flushed and closed and the user never was the wiser about the output. In some cases that's just fine, but I had an application that utilized the Console to provide periodic and frequent updates, effectively notifying the user of status and progress through a lengthy set of operations. I was extremely hesitant to rewrite the application or introduce a TextWriter parameter (substituting for Console.Out) and using that rather than Console or (heaven forbid) introducing a global TextWriter that all classes magically utilized. Besides, the Console object is already there for precisely that purpose.
Therefore, I had made the decision long ago to stick with using Console.WriteLine(), et al and stay the course. However, one obstacle remained: how can I, using Console.Write[Line]() redirect the output to a TextBox (or some other control) without having to wait for the stream to be closed to get the information written to it?
The answer I came up with is to create a special class (in my case I called it FeedbackWriter) that inherits from the abstract TextWriter. Then, I overrode the various WriteXXX() methods to take the string and pump it into the TextBox. NOTE: it may not be sufficient to simply override one Write() or one WriteLine() method, and yes, there are many overloads. Each of these methods on the Console object calls directly into the matching WriteXXX() on the TextWriter so you might have a little work, but once it's done, it's done. Even then, you might not need to do much more than what's below. A quick glance to Reflector shows that the various .Write() and .WriteLine() methods pipe their calls through the string overloads (with the exception of the char and char[] overloads).
My example resembles the following:
[UPDATED 03/06/2006: Removed the assignment to the base.NewLine explicitly - it defaults to “\r\n“ which is the appropriate line break in a TextBox]
internal sealed class FeedbackWriter : TextWriter {
internal FeedbackWriter(TextBox textBox) : base() {
_textBox = textBox;
}
private TextBox _textBox;
public override Encoding Encoding {
get { return Encoding.Default; }
}
// when the Console's Out property is set to other than the default,
// the Console class will create a synchronized, thread-safe TextWriter
// so we don't need to perform the otherwise required calls to
// .InvokeRequired and .Invoke() on the TextBox.
public override void Write(string value) {
_textBox.AppendText(value.Replace("\n", base.NewLine));
}
public override void WriteLine(string value) {
this.Write(value);
// WriteLine() needs to append and additional line break.
_textBox.AppendText(base.NewLine);
}
}
Then, once all of the desired overloads are defined, you can use it simply like this:
FeedbackWriter writer = new FeedbackWriter(txtFeedback);
Console.SetOut(writer);
It's nice and convenient to be able to redirect the console output like this and not have to make any other changes to the application. This discussion is not really complete, but it potentially provides the basis for some future posts on the topic, if I feel so inclined or have the requests.