Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting the color for Console.Error writes

I’m writing a console application that has a custom logger in it. The logger needs to color anything sent to Console.Error in red. I now have third party references that also write to Console.Out and Console.Error so I have to do this in a way that accounts for them too since I don’t have their source code. I’ve setup my logger so that any code writing to the Console will be using my logger’s TextWriter’s by calling the Console.SetOut & Console.SetError methods. Its kinda-of working but I’m guessing there is some sort of synchronization issue? In my ErrorWriter class you can see I’m setting the console’s foreground color and then calling base.Write() but the result is not as expected. Text coming from Console.Out that should be gray is coming out red and mid-stream it suddenly turns to gray. It’s been consistently changing color from red back to gray at the same character position but I’m assuming that base.Write() doesn’t actually spit out to the Console immediately; there is some kind of lag time/buffer. I’ve tried calling base.Flush() but that makes ALL of the text from Console.Out red which is even worse. How do I solve this problem?

public class Logger
{
    private static TextWriter _out;
    private static ErrorWriter _error;

    public Logger()
    {
        Initiliaze();
    }

    public static TextWriter Out
    {
        get
        {
            return _out;
        }
    }

    public static TextWriter Error
    {
        get
        {
            return _error;
        }
    }

    private static void Initiliaze()
    {
        if (_out == null)
            _out = new StreamWriter(Console.OpenStandardOutput());
        if (_error == null)
            _error = new ErrorWriter(Console.OpenStandardError());

        Console.SetOut(Out);
        Console.SetOut(Error);
    }
}

public class ErrorWriter : StreamWriter
{
    // constructors omitted to save space

    public override void Write(string value)
    {
            Console.ForegroundColor = ConsoleColor.Red;
            base.Write(value);
            //base.Flush();
            Console.ResetColor();
    }

    public override Encoding Encoding
    {
        get { return Encoding.Default; }
    }
}
like image 792
TugboatCaptain Avatar asked May 10 '12 11:05

TugboatCaptain


People also ask

What is default console color?

A ConsoleColor that specifies the foreground color of the console; that is, the color of each character that is displayed. The default is gray.


2 Answers

You can decorate the method in order to do that:

public class ConsoleErrorWriterDecorator : TextWriter
{
    private TextWriter m_OriginalConsoleStream;

    public ConsoleErrorWriterDecorator(TextWriter consoleTextWriter)
    {
        m_OriginalConsoleStream = consoleTextWriter;
    }

    public override void WriteLine(string value)
    {
        ConsoleColor originalColor = Console.ForegroundColor;
        Console.ForegroundColor = ConsoleColor.Red;

        m_OriginalConsoleStream.WriteLine(value);

        Console.ForegroundColor = originalColor;
    }

    public override Encoding Encoding
    {
        get { return Encoding.Default; }
    }

    public static void SetToConsole()
    {
        Console.SetError(new ConsoleErrorWriterDecorator(Console.Error));
    }
}

Don't forget to run "ConsoleErrorWriterDecorator.SetToConsole();" before you start writing to console

like image 108
eyossi Avatar answered Oct 12 '22 22:10

eyossi


Turned out to be a stupid copy/paste error! I had two calls to Console.SetOut(). Now its working after change the second one to Console.SetError()

like image 41
TugboatCaptain Avatar answered Oct 12 '22 21:10

TugboatCaptain