Using PowerShell To Check That Windows Server Services Set To Automatic Have Started

Following on from the blog post Testing TCP Port Response from PowerShell  which provided a means to check that servers had fully rebooted after a patching and reboot cycle, I needed to take this one step further and check that all of the Windows Services set to Automatic successfully started after the reboot.

This should be pretty straightforward since we have a Get-Service cmdlet. Unfortunately however, this cmdlet does not return a StartMode parameter, i.e. it’s not possible to tell whether the Startup Type has been set to Automatic, Manual or Disabled. This is quite a large gap in my opinon - if you agree with me you can vote to get it included in a future release here. Of course with PowerShell there’s usually another way to achieve the same objective and using Get-WMIObject it is possible to find out the Startup Type of the service.


Get-WmiObject Win32\_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State='Stopped' AND Name!='SysmonLog'"

Notice that we filter out the Perfmon service (SysmonLog) since it is rarely in a started state.

One other thing to watch out for in this script is that the section


catch \[System.Exception\]

which is there to catch any WMI queries that fail, e.g. the server hasn’t rebooted properly or the correct permissions do not exist to make the WMI query, will not pick up any of these failures. This is because try / catch will only catch terminating errors and the WMI failures are non terminating. We can work around this by setting:


$ErrorActionPreference = "Stop"

and then back to normal afterwards:


$ErrorActionPreference = "Continue"

The script accepts pipeline input, so for example you could run it like:


Get-Content servers.txt | ./Get-AutomaticServiceState.ps1

Here it is:


<# .SYNOPSIS Retrieves any Windows services set to Automatic and are not running

.DESCRIPTION Retrieves any Windows services set to Automatic and are not running

.PARAMETER  ComputerName Name of the computer to test the services for

.EXAMPLE PS C:\\> Get-AutomaticServiceState -ComputerName Server01

.EXAMPLE PS C:\\> Get-Content servers.txt | Get-AutomaticServiceState

.NOTES Author: Jonathan Medd Date: 11/01/2012 #>

\[CmdletBinding()\] param( \[Parameter(Position=0,Mandatory=$true,HelpMessage="Name of the computer to test", ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$true)\] \[Alias('CN','\_\_SERVER','IPAddress','Server')\] \[System.String\] $ComputerName )

process {

try {

\# Set ErrorActionPreference to Stop in order to catch non-terminating WMI errors $ErrorActionPreference = "Stop"

\# Query the server via WMI and exclude the Performance Logs and Alerts Service $WMI = Get-WmiObject Win32\_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State='Stopped' AND Name!='SysmonLog'"

}

catch \[System.Exception\]

{ $WMI = “” | Select-Object SystemName,Displayname,StartMode,State $WMI.SystemName = $ComputerName $WMI.Displayname = "Unable to connect to server" $WMI.StartMode = "" $WMI.State = "" }

finally {

$ErrorActionPreference = "Continue"

}

if ($WMI){

foreach ($WMIResult in $WMI){

$MYObject = “” | Select-Object ComputerName,ServiceName,StartupMode,State $MYObject.ComputerName = $WMIResult.SystemName $MYObject.ServiceName = $WMIResult.Displayname $MYObject.StartupMode = $WMIResult.StartMode $MYObject.State = $WMIResult.State $MYObject } } }