Color is a very important part of our lives. Traffic lights use color to relay vital information. PowerShell error and warning messages use color to grab your attention. Many species of birds use color to attract a mate. I use color to highlight things I don’t want to miss. Follow along and I’ll show you how I do it.

Basic Select-Object

Let’s take the Get-Service cmdlet. For our example, we aren’t concerned with what the command does as much as the output. If we run the command below we get our three fields in plain, boring monochrome.

Get-Service | Select-Object DisplayName, Status, StartType

We have two fields that have a fixed number of options. If we could color code these options, it would be a lot easier to read. We could tell at a glance which services were disable or stopped.

Calculated Properties

If you haven’t used Calculated Properties, you are missing out on some powerful functionality. The barest explanation is instead of a property, you provide a hash table. The hash takes two values, Name/Label and Expression. star can be shortened to n and e. Using our previous example we can rename a property for display very similar to a SQL query selecting a column AS some other name.

#                                    hash  new name  pipeline
Get-Service | Select-Object DisplayName,@{n="RunStop"<# New Name #>;e={$_.Status}<# Real name from the pipeline #>}, StartType
The next step is to do something more with the expression.

Get-Service | Select-Object DisplayName, @{n='Status';e={if($_.Status -eq 'Running'){'RUNNING!'}else{$_.Status}}}  
That ends up being a lot to put on the command line. Matching up parentheses and curly braces gets to be a pain. One of the great things about the expression portion of the property is that it’s essentially a small script block so we can put all the logic in a scriptblock variable and just use that making readability much easier.
[scriptblock]$exp = {
	if($_.Status -eq 'Running'){
	}elseif($_.Status -eq 'Stopped'){
		# since paused, stopping and starting are also options we'll
		# just pass through the status unchanged for those.
so our calculated property is now this.
Get-Service | Select-Object DisplayName, @{n='Status';e=$exp}  

ANSI Escape Sequences

Finally we get to the color part of this post. There are plenty of references and tutorials out there that go into more detail. Here’s a very brief list.

The basic formula is ESCAPE + [ + # + m.

Foreground Background Color
30 40 Black
31 41 Red
32 42 Green
33 43 Yellow
34 44 Blue
35 45 Magenta
36 46 Cyan
37 47 White
0 Reset

ANSI escapes are interpreted by the console for display and are in effect until turned off. So if we start the red color it will keep going until we send the reset command. Don’t worry. There will be an example.

#PowerShell 5.1
$esc = [char]27; # escape character
$red = $esc + '[31m';$green = $esc + '[32m';
$reset = $esc + '[0m';
# PowerShell 7 has escape character builtin using `e
$red = "`e[31m";$green = "`e[32m"
$reset = "`e[0m";

Putting it all together

Now that we know that we know we can use a scriptblock variable and we have our color commands we can make the magic happen.

Let’s make a new scriptblock

[scriptblock]$exp2 = {
	if($_.Status -eq 'Running'){
		# using string substitution we change Running to 
		# Green and reset at the end.
		$("{0}Running{1}" -f $green, $reset);
	}elseif($_.Status -eq 'Stopped'){
		# Then we changed Stopped to red and reset.
		$("{0}Stopped{1}" -f $red, $reset);
Get-Service | Select-Object DisplayName, @{n='Status';e=$exp2}  

So there you have it. A couple of caveats are that any sorting you try to do using the colored field will be off. The screen hides the ANSI sequence but it’s still there and the pipeline sees it. Likewise if you output to file, you’ll see the ANSI codes.