278

Writing a small command line tool, it would be nice to output in different colours. Is this possible?

NibblyPig
  • 51,118
  • 72
  • 200
  • 356

14 Answers14

371

Yes. See this article. Here's an example from there:

Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine("White on blue.");

enter image description here

Malice
  • 3,927
  • 1
  • 36
  • 52
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
160
class Program
{
    static void Main()
    {
        Console.BackgroundColor = ConsoleColor.Blue;
        Console.ForegroundColor = ConsoleColor.White;
        Console.WriteLine("White on blue.");
        Console.WriteLine("Another line.");
        Console.ResetColor();
    }
}

Taken from here.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
74

Above comments are both solid responses, however note that they aren't thread safe. If you are writing to the console with multiple threads, changing colors will add a race condition that can create some strange looking output. It is simple to fix though:

public class ConsoleWriter
{
    private static object _MessageLock= new object();

    public void WriteMessage(string message)
    {
        lock (_MessageLock)
        {
            Console.BackgroundColor = ConsoleColor.Red;
            Console.WriteLine(message);
            Console.ResetColor();
        }
    }
}
ΩmegaMan
  • 29,542
  • 12
  • 100
  • 122
Roger Hill
  • 3,677
  • 1
  • 34
  • 38
  • 20
    Writing from multiple threads without synchronisation will result in garbled output even if there are no color changes: it's not just changing colors that causes a race condition – Joe Jul 05 '17 at 09:41
  • 10
    @Joe A single `Write` call will **not** be garbled. See https://stackoverflow.com/questions/4812508/is-console-writeline-thread-safe. It's just the order of the write-calls which is not "safe". – BatteryBackupUnit Oct 17 '17 at 09:29
  • But what about if other processes are writing to the same console? They won't be using your lock object. Is there any truly atomic way to change the color, write to the console, and then change the color back? – Kyle Delaney Sep 01 '20 at 18:52
  • 1
    They won't be using the console writer if you don't choose to use the console writer. The implication here is that you use this object for all writes to the console. I suppose you could do some tricky wrapper on the Console.Write command, but that sees a bit overkill. – Roger Hill Sep 03 '20 at 17:41
  • It feels to me like the `WriteMessage` method - or maybe even the whole class - should be static. – Stewart Dec 22 '22 at 17:46
  • It could be if you want it to. The lock needs to be static to block other threads from writing at the same time. I didn't make it static for the example to just keep the sample as simple as possible. – Roger Hill Dec 30 '22 at 09:52
60

I've created a small plugin (available on NuGet) that allows you to add any (if supported by your terminal) color to your console output, without the limitations of the classic solutions.

It works by extending the String object and the syntax is very simple:

"colorize me".Pastel("#1E90FF");

Both foreground and background colors are supported.

enter image description here

silkfire
  • 24,585
  • 15
  • 82
  • 105
  • 4
    I believe this library uses those [ANSI escape color codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors), which appears to be what [Microsoft.Extensions.Logging.Console](https://github.com/dotnet/runtime/blob/master/src/libraries/Microsoft.Extensions.Logging.Console/src/AnsiParser.cs) is also using. – Pang Oct 16 '20 at 03:01
  • 2
    @Pang Microsoft.Extensions.Logging.Console is a logging library, whereas Pastel can be used for printing directly to the console; also it seems to be supporting a limited subset of colors from what I can derive from the source code. – silkfire Oct 16 '20 at 08:38
  • 1
    @Pang that library does not implement all foreground colors for some reason. I tend to go with Microsoft solutions but the Pastel solution is more complete. – Tono Nam Jan 19 '22 at 23:26
20

Here is a simple method I wrote for writing console messages with inline color changes. It only supports one color, but it fits my needs.

// usage: WriteColor("This is my [message] with inline [color] changes.", ConsoleColor.Yellow);
static void WriteColor(string message, ConsoleColor color)
{
    var pieces = Regex.Split(message, @"(\[[^\]]*\])");

    for(int i=0;i<pieces.Length;i++)
    {
        string piece = pieces[i];
        
        if (piece.StartsWith("[") && piece.EndsWith("]"))
        {
            Console.ForegroundColor = color;
            piece = piece.Substring(1,piece.Length-2);          
        }
        
        Console.Write(piece);
        Console.ResetColor();
    }
    
    Console.WriteLine();
}

image of a console message with inline color changes

Pang
  • 9,564
  • 146
  • 81
  • 122
Walter Stabosz
  • 7,447
  • 5
  • 43
  • 75
  • code is fine but it lacks the explanation, what are you doing? – Leandro Bardelli Apr 19 '23 at 17:34
  • Are you asking for me to comment the code? I thought it was fairly self-explanatory. The function scans the string named `message` for text wrapped in square-brackets and sets the `Console.ForegroundColor` property to print out yellow text, writes the text to the console, then it resets the text to the default ForegroundColor. I don't believe an SO answer necessitates so much detail. For me, the primary purpose of an answer is to solve the questions problem, not to educate the asking developer. – Walter Stabosz Apr 19 '23 at 21:56
  • I vote up the answer, but the main idea of SO is a clear answer to explain to others than OP. In this case, the answer is fine but is not related to what the OP asks. What means "pieces", ie., words? letters? what does the regular expression? etc – Leandro Bardelli Apr 19 '23 at 22:10
18

Yes, it's easy and possible. Define first default colors.

Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
Console.Clear();

Console.Clear() it's important in order to set new console colors. If you don't make this step you can see combined colors when ask for values with Console.ReadLine().

Then you can change the colors on each print:

Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Red text over black.");

When finish your program, remember reset console colors on finish:

Console.ResetColor();
Console.Clear();

Now with netcore we have another problem if you want to "preserve" the User experience because terminal have different colors on each Operative System.

I'm making a library that solves this problem with Text Format: colors, alignment and lot more. Feel free to use and contribute.

https://github.com/deinsoftware/colorify/ and also available as NuGet package

Colors for Windows/Linux (Dark):
enter image description here

Colors for MacOS (Light):
enter image description here

Pang
  • 9,564
  • 146
  • 81
  • 122
equiman
  • 7,810
  • 2
  • 45
  • 47
12

The easiest way I found to colorize fragments of the console output is to use the ANSI escape sequences in the Windows console.

public static int Main(string[] args)
{
    string NL          = Environment.NewLine; // shortcut
    string NORMAL      = Console.IsOutputRedirected ? "" : "\x1b[39m";
    string RED         = Console.IsOutputRedirected ? "" : "\x1b[91m";
    string GREEN       = Console.IsOutputRedirected ? "" : "\x1b[92m";
    string YELLOW      = Console.IsOutputRedirected ? "" : "\x1b[93m";
    string BLUE        = Console.IsOutputRedirected ? "" : "\x1b[94m";
    string MAGENTA     = Console.IsOutputRedirected ? "" : "\x1b[95m";
    string CYAN        = Console.IsOutputRedirected ? "" : "\x1b[96m";
    string GREY        = Console.IsOutputRedirected ? "" : "\x1b[97m";
    string BOLD        = Console.IsOutputRedirected ? "" : "\x1b[1m";
    string NOBOLD      = Console.IsOutputRedirected ? "" : "\x1b[22m";
    string UNDERLINE   = Console.IsOutputRedirected ? "" : "\x1b[4m";
    string NOUNDERLINE = Console.IsOutputRedirected ? "" : "\x1b[24m";
    string REVERSE     = Console.IsOutputRedirected ? "" : "\x1b[7m";
    string NOREVERSE   = Console.IsOutputRedirected ? "" : "\x1b[27m";

    Console.WriteLine($"This is {RED}Red{NORMAL}, {GREEN}Green{NORMAL}, {YELLOW}Yellow{NORMAL}, {BLUE}Blue{NORMAL}, {MAGENTA}Magenta{NORMAL}, {CYAN}Cyan{NORMAL}, {GREY}Grey{NORMAL}! ");
    Console.WriteLine($"This is {BOLD}Bold{NOBOLD}, {UNDERLINE}Underline{NOUNDERLINE}, {REVERSE}Reverse{NOREVERSE}! ");
}

The output:

enter image description here

The NOBOLD code is really "normal intensity". See the "SGR (Select Graphic Rendition) parameters" section on the linked wikipedia page for details.

The redirection test avoids outputting escape sequences into a file, should the output be redirected. If the user has a color scheme other than white-on-black, it won't get reset but you could maybe use the Console functions to save/restore the user's color scheme at the beginning and end of the program if that matters.

UweBaemayr
  • 1,861
  • 1
  • 18
  • 21
  • In Windows 10 (C# Console Application) it produces a non colored output "This is ←[91mRed←[39m, ←[92mGreen←[39m, ←[93mYellow←[39m, ←[94mBlue←[39m". Do you know what might be the reason why it does not interpret the codes? – Michael Hutter May 17 '23 at 05:19
  • I have not encountered any issues. However, this page might help. How-to: Use ANSI colors in the terminal: https://ss64.com/nt/syntax-ansi.html . It mentions that Windows versions 1511 through to 1903 require a registry setting. It suggests calling SetConsoleMode API with the ENABLE_VIRTUAL_TERMINAL_PROCESSING flag, or (less desirable) making a registry entry. Try the SetConsoleAPI call from your C# app and post back if that helps. – UweBaemayr May 18 '23 at 15:10
  • I've also had some programs disable the ANSI output -- specifically, some GNU apps on Windows like UNZIP.EXE, especially when they crash or I use Ctrl+Break while running. Guessing they might modify the way the console works and not always restore it when finished. – UweBaemayr May 18 '23 at 15:13
8

Just to add to the answers above that all use Console.WriteLine: to change colour on the same line of text, write for example:

Console.Write("This test ");
Console.BackgroundColor = bTestSuccess ? ConsoleColor.DarkGreen : ConsoleColor.Red;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine((bTestSuccess ? "PASSED" : "FAILED"));
Console.ResetColor();
Daap
  • 345
  • 4
  • 10
7

Here's an elegant implementation using the new string interpolation feature for dotnet.

[InterpolatedStringHandler]
public ref struct ConsoleInterpolatedStringHandler
{
    private static readonly Dictionary<string, ConsoleColor> colors;
    private readonly IList<Action> actions;

    static ConsoleInterpolatedStringHandler() =>
        colors = Enum.GetValues<ConsoleColor>().ToDictionary(x => x.ToString().ToLowerInvariant(), x => x);

    public ConsoleInterpolatedStringHandler(int literalLength, int formattedCount)
    {
        actions = new List<Action>();
    }

    public void AppendLiteral(string s)
    {
        actions.Add(() => Console.Write(s));
    }

    public void AppendFormatted<T>(T t)
    {
        actions.Add(() => Console.Write(t));
    }

    public void AppendFormatted<T>(T t, string format)
    {
        if (!colors.TryGetValue(format, out var color))
            throw new InvalidOperationException($"Color '{format}' not supported");

        actions.Add(() =>
        {
            Console.ForegroundColor = color;
            Console.Write(t);
            Console.ResetColor();
        });
    }

    internal void WriteLine() => Write(true);
    internal void Write() => Write(false);

    private void Write(bool newLine)
    {
        foreach (var action in actions)
            action();

        if (newLine)
            Console.WriteLine();
    }
}

To use it, create a class, such as ExtendedConsole:

internal static class ExtendedConsole
{
    public static void WriteLine(ConsoleInterpolatedStringHandler builder)
    {
        builder.WriteLine();
    }

    public static void Write(ConsoleInterpolatedStringHandler builder)
    {
        builder.Write();
    }
}

Then, use it like:

        var @default = "default";
        var blue = "blue";
        var green = "green";
        ExtendedConsole.WriteLine($"This should be {@default}, but this should be {blue:blue} and this should be {green:green}");

enter image description here

JobaDiniz
  • 862
  • 1
  • 14
  • 32
6

A sample method to color multiple words at the same time.

private static void WriteColor(string str, params (string substring, ConsoleColor color)[] colors)
{
    var words = Regex.Split(str, @"( )");

    foreach (var word in words)
    {
        (string substring, ConsoleColor color) cl = colors.FirstOrDefault(x => x.substring.Equals("{" + word + "}"));
        if (cl.substring != null)
        {
            Console.ForegroundColor = cl.color;
            Console.Write(cl.substring.Substring(1, cl.substring.Length - 2));
            Console.ResetColor();
        }
        else
        {
            Console.Write(word);
        }
    }
}

Usage:

WriteColor("This is my message with new color with red", ("{message}", ConsoleColor.Red), ("{with}", ConsoleColor.Blue));

Output:

enter image description here

Rans
  • 569
  • 7
  • 14
6

I developed a small fun class library named cConsole for colored console outputs.
Example usage:

const string tom = "Tom";
const string jerry = "Jerry";
CConsole.WriteLine($"Hello {tom:red} and {jerry:green}");

It uses some functionalities of C# FormattableString, IFormatProvider and ICustomFormatter interfaces for setting foreground and background colors of text slices.
You can see cConsole source codes here

Ramin Rahimzada
  • 452
  • 6
  • 10
5

Yes, it is possible as follows. These colours can be used in a console application to view some errors in red, etc.

Console.BackgroundColor = ConsoleColor.Blue;
Console.ForegroundColor = ConsoleColor.White;//after this line every text will be white on blue background
Console.WriteLine("White on blue.");
Console.WriteLine("Another line.");
Console.ResetColor();//reset to the defoult colour
Pang
  • 9,564
  • 146
  • 81
  • 122
Chamila Maddumage
  • 3,304
  • 2
  • 32
  • 43
0

I did want to just adjust the text color when I want to use Console.WriteLine(); So I had to write

Console.ForegroundColor = ConsoleColor.DarkGreen;
Console.WriteLine("my message");
Console.ResetColor();

every time that I wanted to write something

So I invented my WriteLine() method and kept using it in Program class instead of Console.WriteLine()

public static void WriteLine(string buffer, ConsoleColor foreground = ConsoleColor.DarkGreen, ConsoleColor backgroundColor = ConsoleColor.Black)
{
   Console.ForegroundColor = foreground;
   Console.BackgroundColor = backgroundColor;
   Console.WriteLine(buffer);
   Console.ResetColor();
}

and to make it even easier I also wrote a Readline() method like this:

public static string ReadLine()
{
   var line = Console.ReadLine();
   return line ?? string.Empty;
}

so now here is what we have to do to write or read something in the console:

static void Main(string[] args) {
   WriteLine("hello this is a colored text");
   var answer = Readline();
}
SReza S
  • 151
  • 1
  • 9
0

With this simple C# code you can demonstrate all possible output colors and choose what you want.

enter image description here

Type type = typeof(ConsoleColor);
Console.ForegroundColor = ConsoleColor.White;
foreach (var name in Enum.GetNames(type))
{
    Console.BackgroundColor = (ConsoleColor)Enum.Parse(type, name);
    Console.WriteLine(name);
}
Console.BackgroundColor = ConsoleColor.Black;
foreach (var name in Enum.GetNames(type))
{
    Console.ForegroundColor = (ConsoleColor)Enum.Parse(type, name);
    Console.WriteLine(name);
}
Michael Hutter
  • 1,064
  • 13
  • 33