The .NET static Console class provides input and output features to console applications. However, the features are quite basic and do not make it easy to format data, and using colour can be quite awkward.
The Console Toolkit provides enhanced facilities that are designed to make it easy to produce better formatted output to the console. You are not forced to use the enhanced console over the default, even if the examples in this documentation seem to encourage it.
The enhanced features are delivered through two interfaces:
IConsoleAdapter
IErrorAdapter
Both of these interfaces derive from IConsoleOperations
which defines the supported output methods. This means that you can use the same formatting and colouring facilities for both standard output and error output, and in fact, if you rely on IConsoleOperation
directly, you can write code that doesn’t care which is being used.
Console applications can output to two standard streams:
Console.WriteLine
write to this stream.Error
property. To write to this you might use calls such as Console.Error.WriteLine()
. Many console applications don’t bother with the error stream and output everything to StdOut.The Toolkit’s approach is to treat these two streams a little more equitably, by giving both adapters that offer identical output facilities.
To access the streams, specify parameters on your [CommandHandler]
with IConsoleAdapter and IErrorAdapter types.
Console output can be redirected to files. For example:
dir > dir.txt
Would run the built in dir
command and the output will be written to a text file called “dir.txt”. The >
character tells the command line interpreter to attach the file as StdOut in place of the visible console window.
StdErr can also be redirected:
dir 2> dir.txt
Here, 2>
indicates that it’s the error output that should be redirected. In this example, the directory information would be emitted to the console window.
If a Console Toolkit based application has its output redirected, the Toolkit will detect it and will ignore colour directives. Formatting that relies on the window size will still use the window size to perform word wrapping or format tables.
StdErr has a specific purpose. After all, it would be easier just to have one output stream for everything, right?
The reason for StdErr is to display diagnostic information about problems that you need to see, even if StdOut is redirected. Consider this example:
dir | find "git" > gitfiles.txt
This runs dir
, searches the output for the text “git”, and the result is written to a text file called “gitfiles.txt”.
If “dir” failed and wrote its error to StdOut, the error would be searched by find
, resulting in a silent failure and a useless “gitfiles.txt”. Because the error had not been made visible, you would not be aware that something had gone wrong.
Fortunately, dir
and find
output their errors on StdErr:
dir ::: | find "git" xxx > gitfiles.txt
Gives:
The system cannot find the path specified.
File not found - XXX
This is still not perfect, because you can’t tell which command emitted the messages. It happens to be one from each program in this case.
In the Unix world, there is a convention that output to StdErr should be prefixed with the program name. If dir
and find
followed that convention, the output might have looked like this:
DIR: The system cannot find the path specified.
FIND: File not found - XXX
The Console Toolkit embraces this convention and will automatically prefix all lines written via the IErrorAdapter with the program name. For example:
SampleCommandApp: Unexpected argument "xxx"
So, getting back to the question, “When to write to StdErr?”, the answer is basically, whenever you are reporting information that would help diagnose why your program was unable to run correctly.
The Toolkit will automatically output command line parsing errors and unhandled exceptions to StdErr, which is sufficient in many cases, but if you intercept an unexpected condition in your code and it is represents a failure, you will need to report the pertinent information via IErrorAdapter.