Powershell: Console Colors

A brief reminder for the topic of Console Colors and Powershell.

Note: All the steps described here will only be applied to the current Powershell session!
If you want to change the colors in your environment permanently, you need to put it into your Powershell profile!

(There are also ways to set some colors via the Window/Terminal/Whatever properties, but in comparison, I find them a bit limited, cumbersome and also ephemeral; I prefer the PS profile approach…)

Get current color setup

The standard values can be seen via $Host (which only accepts one of the few values from [System.ConsoleColor], see below):

> $Host.UI.RawUI.BackgroundColor
Black

> $Host.UI.RawUI.ForegroundColor
Gray

> $Host.PrivateData

ErrorForegroundColor    : Red
ErrorBackgroundColor    : Black
WarningForegroundColor  : Yellow
WarningBackgroundColor  : Black
DebugForegroundColor    : Yellow
DebugBackgroundColor    : Black
VerboseForegroundColor  : Yellow
VerboseBackgroundColor  : Black
ProgressForegroundColor : Yellow
ProgressBackgroundColor : DarkCyan

PSReadLine (read below) offers more things to customize and also in different formats (most of it hasn’t been interesting to me yet):

> Get-PSReadLineOption

[...]
TypeColor       : "$([char]0x1b)[37m"
VariableColor   : "$([char]0x1b)[92m"

Note:

Set new colors

Originally, Powershell supported only these 16 predefined colors (with names):

> [System.ConsoleColor].GetEnumNames()

Black
DarkBlue
DarkGreen
DarkCyan
DarkRed
DarkMagenta
DarkYellow
Gray
DarkGray
Blue
Green
Cyan
Red
Magenta
Yellow
White

But nowadays, there is also PSReadLine, which is even included with Powershell 5.1 in some versions.

And with Set-PSReadLineOption -Colors ... there are now more and more elaborate ways to define style and color with ANSI Escape Code sequences (but that is slightly more involved and laborious).

Helpful links:

Example

Play and test.
And if you like the result and want to keep it: Put in in your profile.

$Host.UI.RawUI.BackgroundColor            = 'Black'
$Host.UI.RawUI.ForegroundColor            = 'Gray'

#$Host.PrivateData.ErrorBackgroundColor    = 'Black'
#$Host.PrivateData.ErrorForegroundColor    = 'Red'
#
#$Host.PrivateData.WarningBackgroundColor  = 'Black'
#$Host.PrivateData.WarningForegroundColor  = 'Yellow'
#
#$Host.PrivateData.DebugBackgroundColor    = 'Black'
#$Host.PrivateData.DebugForegroundColor    = 'Yellow'
#
#$Host.PrivateData.VerboseBackgroundColor  = 'Black'
#$Host.PrivateData.VerboseForegroundColor  = 'Cyan'
#
#$Host.PrivateData.ProgressBackgroundColor = 'DarkCyan'
#$Host.PrivateData.ProgressForegroundColor = 'Yellow'

Set-PSReadLineOption -Colors @{
    #Command             = ''
    Comment             = 'Cyan'
    #ContinuationPrompt  = ''
    #Default             = ''
    #Emphasis            = ''
    #Error               = ''
    #Keyword             = ''
    #Member              = ''
    #Number              = ''
    #Operator            = ''
    #Parameter           = ''
    #Selection           = ''
    #String              = ''
    #Type                = ''
    #Variable            = ''

    # --- As an ANSI escape sequence (for a 256 color table): ---
    #Comment = "$([char]0x1b)[38;5;100m" # Bronze

    # --- As a RGB value in hexadecimal for 24-bit color: ---
    #Comment = "#f0a5bf"                 # Pink
}

On ANSI escape code sequences

Here’s an extremely brief overview of the concept.
This example sets a bronze foreground color:

$ESC[38;5;100m ─── m signals the end of the SGR control sequence
 │  ││  │
 │  ││  ╰─ 5;n     : n is an index (0-255) into a color table (see below)
 │  ││     2;r;g;b : Red/Green/Blue values (each in the range of 0-255) (see below)
 │  ││
 │  │╰─ Select Graphic Rendition (SGR) parameter: 38 = "Foreground color"
 │  │                                             48 = "Background color"
 │  │                                                                              
 │  ╰─ [ -> Control Sequence Introducer (CSI)
 │
 ╰─ $ESC or [char]0x1b -> The 'Escape' character
                          or as $ESC = $([char]0x1b)
                          Could also be used as `e in Powershell 7

The Select Graphic Rendition control sequence (CSI n m) offers many parameters to set display attributes, not just background and foreground colors; also bold, italic, underline, blinking, inverse and so on (several attributes can be set in the same sequence, separated by semicolons).

Not all features are supported in all terminals (or versions of Windows, Terminal/Shell/Host or Powershell (esp. 5.1))!

Helpful links:

Example

One can do a lot of stuff with ANSI Escape Code sequences (I haven’t even mentioned cursor movements etc.), but it’s also not too easy to write or read, if applied directly.

A practical compromise is to pre-define some variables and use those to composite a format string:

$ESC   = [char]0x1b
$Reset = "$ESC[0m"

# RGB color format : 2;<R>;<G>;<B>
# Color table entry: 5;<index>
$RedFG            = "$ESC[38;2;255;0;0m"
$BlueBG           = "$ESC[48;2;0;0;255m"
$GreenBG_YellowFG = "$ESC[48;2;0;80;0m$ESC[38;2;255;255;0m"

$Blink         = "$ESC[5m"
$Bold          = "$ESC[1m"
$Dim           = "$ESC[2m" # Added in PowerShell 7.4
$Reverse       = "$ESC[7m"
$Italic        = "$ESC[3m"
$Underline     = "$ESC[4m"
$Strikethrough = "$ESC[9m"

$str1 = "default, {1}red foreground{0}, default, {2}blue background{0}, default, {3}green background, yellow foreground{0}, default"                        -f $Reset, $RedFG, $BlueBG, $GreenBG_YellowFG
$str2 = "default, {1}italic {0}, default, {2}{3}underlined & bold{0}, default, {4}{5}strikethrough on inverse{0}, default"                                  -f $Reset, $Italic, $Underline, $Bold, $Strikethrough, $Reverse
$str3 = "default, {1}{4}italic red{0}, default, {2}{5}{6}underlined & bold on blue{0}, default, {3}{7}{8}strikethrough on inverse green/yellow{0}, default" -f $Reset, $RedFG, $BlueBG, $GreenBG_YellowFG, $Italic, $Underline, $Bold, $Strikethrough, $Reverse

Write-Host -Object $str1, $str2, $str3 -Separator "`n`n"

Which should look similar to this (in both Powershell 5.1 and 7.x):

Example 1

Tip

If you have hardwired colors in your code, it’s maybe a good idea to make it more adaptable to the user’s preferences:

function WriteError ($str)
{
    write-host ("{0,-5} | {1}" -f 'ERROR', $str) -BackgroundColor $Host.PrivateData.ErrorBackgroundColor `
                                                 -ForegroundColor $Host.PrivateData.ErrorForegroundColor
}

WriteError "Foo!"