Domain Controller Status Lights via PowerShell

In an previous article, I showed you several different techniques for displaying critical service statuses from your domain controllers. Although you could easily apply the technique to any server or service, I prefer PowerShell commands and tools that work with objects in the pipeline. This is especially true if you think you might need to sort, filter, export, or convert the results. But there are probably just as many situations where all you want to do is read some information on the screen. PowerShell has some tricks up its sleeve that you can take advantage of to make this kind of reporting easy and meaningful. All I ask is that you realize that what I’m about to demonstrate should be considered the exception and not the rule.

Let’s use the same domain controllers and services that I used last time.

$dcs = "chi-dc01","chi-dc02","chi-dc04"
$svcs = "adws","dns","kdc","netlogon"

Next, let’s look at a typical command you might run.

Get-Service -name $svcs -ComputerName $dcs |
format-table @{Name="Computername";Expression={$_.Machinename.toUpper()}},Name,Displayname,Status -AutoSize

Checking domain controller services (Image Credit: Jeff Hicks)
Checking domain controller services (Image Credit: Jeff Hicks)

As you can see, I have some services that are stopped. I’d like those to stand out. This will require a little text manipulation. Format-Table writes formatting objects to the pipeline, but I like the result, so I’ll re-run the command and turn it into strings using Out-String.

$t = Get-Service -name $svcs -ComputerName $dcs |
format-table @{Name="Computername";Expression={$_.Machinename.toUpper()}},Name,Displayname,Status -AutoSize |
out-string

This looks the same.

A text version of the table (Image Credit: Jeff Hicks)
A text version of the table (Image Credit: Jeff Hicks)

I will need to split this into multiple lines so that I can process them individually. I will split them into an array on the new line character.

$split = $t.split("`n")

See how I now have an array of strings?

Viewing the split string (Image Credit: Jeff Hicks)
Viewing the split string (Image Credit: Jeff Hicks)

My intention is to colorize services that are not running. Most of the time Get-Service shows either running or stopped, but there are potentially other states. These are defined in a special type of an object called an enumeration. You can list enumerations with the .NET Framework and the [enum] class. Use the GetNames() method, and specify the name of the enumeration class.

 [enum]::GetNames([System.ServiceProcess.ServiceControllerStatus])

Service status enumerations (Image Credit: Jeff Hicks)
Service status enumerations (Image Credit: Jeff Hicks)

I intend to flag stopped services in red and any status other that’s running in yellow. I’ll use a regular expression pattern to identity the status, which I can build from the enumeration.

$other = ([enum]::GetNames([System.ServiceProcess.ServiceControllerStatus])).where({$_ -notmatch "running|stopped"}) -join "|"

Note that I am using the Where() method, introduced in PowerShell 4.0. You can also use the Where-Object
cmdlet. The variable looks like this:

A regular expression pattern (Image Credit: Jeff Hicks)
A regular expression pattern (Image Credit: Jeff Hicks)


Now, I have several options. Here’s the first approach you could take.

foreach ($line in $split) {
#hashtable of parameters for Write-Host
$params=@{Object=$line}
if ($line -match "Stopped") {
$params.Add("BackgroundColor","red")
}
elseif ($line -match $other) {
$params.Add("BackgroundColor","yellow")
}
Write-Host @params
}

I am using the ForEach enumerator, which makes this a little easier to follow. For every item ($line) in the collection $split, I am doing several things. First, I create a hashtable of parameter values that I intend to splat to Write-Host. I like this approach because I can dynamically adjust parameters based on my needs.
In this case, if the line has the word “Stopped” in it, I’ll set the Backgroundcolor parameter to Red. Or if the string matches anything in my regular expression, I’ll set it to yellow. If there is no match, then the BackgroundColor parameter is undefined when I splat the hashtable to Write-Host.
Here’s my result.

Highlighting stopped services (Image Credit: Jeff Hicks)
Highlighting stopped services (Image Credit: Jeff Hicks)

Another option is to insert a Red/Green traffic light using Write-Host.

foreach ($line in $split) {
#append some space after the line
Write-Host "$line " -NoNewline
if ($line -match "Stopped") {
Write-Host " " -BackgroundColor Red -NoNewline
}
Write-Host " "
}

In this example, if the line matches Stopped, I’ll write a blank space with red background color, which gives me this result:

Red light for stopped services (Image Credit: Jeff Hicks)
Red light for stopped services (Image Credit: Jeff Hicks)

I used a space, but you could use any character you want that is supported in your PowerShell host. I should point out that I have been using the PowerShell ISE. If you intend to use the PowerShell console, you most likely will need to experiment with Write-Host to get the desired results. Here’s a variation that will only work in the PowerShell console with a special character.

$marker = [char]31
foreach ($line in $split) {
#only process lines with text
if ($line -notmatch "^\s+$") {
#replace line return with a space
Write-Host $($line.Replace("`r"," ")) -NoNewline
if ($line -match "Stopped") {
Write-Host $marker -foregroundColor Red
}
else {
Write-Host "`r"
}
}
else {
#should be blank lines
Write-Host $line
}
}

A PowerShell console variation (Image Credit: Jeff Hicks)
A PowerShell console variation (Image Credit: Jeff Hicks)


I have a few other variations I want to show you, but I’m afraid your head might be buzzing, so I think we’ll wrap this up for now. Again, playing with text like this is fun and potentially useful, but should be considered an exception to how you normally use PowerShell. Give the code samples a try and see for yourself how this all works. Next time we’ll look at a few more options.