[bgreco.net]: PS C:\> Format-Color

Format-Color is a small function that you can slap on the end of a PowerShell command pipeline to colorize the command's output based on line-by-line pattern matching.

Why might such a function be useful?

PowerShell is all about passing objects around. Let's say you've already written a function Get-DomainComputer that returns a list of all computers in the domain, and you want a report of their basic OS info. It might look something like this:

function Get-DomainComputerInfo {
	foreach($computer in Get-DomainComputer) {
		Get-WmiObject -ComputerName $computer Win32_OperatingSystem | Select-Object CSName, Version, OSArchitecture
	}
}

that outputs something like this:

PS C:\> Get-DomainComputerInfo
CSName         Version        OSArchitecture
------         -------        --------------
BENDER         6.1.7601       64-bit        
LEELA          6.1.7601       64-bit        
FRY            6.1.7600       64-bit        
FARNSWORTH     6.1.7601       32-bit        

Now, let's say your boss wants a pretty report with all the out-of-date systems in red, and the 32-bit systems in green because you still need to keep a couple of them around to run legacy software.

One way (hint: the wrong way) of doing this is to start cluttering your function with a bunch of conditional calls to Write-Host with a ForegroundColor. But now, your slick function no longer emits objects. This means that you can no longer use the PowerShell sorting or grouping cmdlets on your function's output. Additionally, you can no longer redirect the output (say, to a file) because it is being written directly to the host application.

A nicer way of colorizing the output while leaving your function intact is to add one final step to the pipeline whose job it is to add the colors. This is the problem that Format-Color attempts to streamline:

PS C:\> Get-DomainComputerInfo | Format-Color @{'6.1.7600' = 'Red'; '32-bit' = 'Green'}
CSName         Version        OSArchitecture
------         -------        --------------
BENDER         6.1.7601       64-bit        
LEELA          6.1.7601       64-bit        
FRY            6.1.7600       64-bit        
FARNSWORTH     6.1.7601       32-bit        

And without further ado, the function itself:

function Format-Color([hashtable] $Colors = @{}, [switch] $SimpleMatch) {
	$lines = ($input | Out-String) -replace "`r", "" -split "`n"
	foreach($line in $lines) {
		$color = ''
		foreach($pattern in $Colors.Keys){
			if(!$SimpleMatch -and $line -match $pattern) { $color = $Colors[$pattern] }
			elseif ($SimpleMatch -and $line -like $pattern) { $color = $Colors[$pattern] }
		}
		if($color) {
			Write-Host -ForegroundColor $color $line
		} else {
			Write-Host $line
		}
	}
}

To use, pass Format-Color a hash table of the form @{'pattern1' = 'Color1'[; ...]}. The colors can be any color recognized by Write-Host. To use a simple wildcard match instead of a regular expression, pass the -SimpleMatch switch.