Last Update: Sep 04, 2024 | Published: Dec 17, 2015
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
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.
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?
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])
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:
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.
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:
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 } }
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.