NibblyPig
NibblyPig

Reputation: 52952

Is it possible to write to the console in colour in .NET?

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

Upvotes: 308

Views: 287525

Answers (14)

Michael Hutter
Michael Hutter

Reputation: 1542

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);
}

Upvotes: 5

UweBaemayr
UweBaemayr

Reputation: 2329

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.

Upvotes: 34

JobaDiniz
JobaDiniz

Reputation: 1013

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

Upvotes: 10

Ramin Rahimzada
Ramin Rahimzada

Reputation: 502

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

Upvotes: 8

Rans
Rans

Reputation: 602

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

Upvotes: 7

SReza S
SReza S

Reputation: 192

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();
}

Upvotes: 0

Walter Stabosz
Walter Stabosz

Reputation: 7735

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

Upvotes: 27

Chamila Maddumage
Chamila Maddumage

Reputation: 3876

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

Upvotes: 5

equiman
equiman

Reputation: 8142

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

Upvotes: 20

Daap
Daap

Reputation: 365

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();

Upvotes: 8

silkfire
silkfire

Reputation: 26033

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

Upvotes: 73

Roger Hill
Roger Hill

Reputation: 4128

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();
        }
    }
}

Upvotes: 79

Mark Byers
Mark Byers

Reputation: 839114

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

Upvotes: 395

Darin Dimitrov
Darin Dimitrov

Reputation: 1039438

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.

Upvotes: 170

Related Questions