PowerShell script to check the service status on a list of PC's

Topics: Developer Forum, PolyMon 2.x, User Forum
Aug 16, 2013 at 3:01 PM
Edited Aug 19, 2013 at 4:38 PM
Here's a Polymon/Powershell script that will go through a list of PC's and check for a list of services to be running.
     $ComputerNames = "pcnumber1","pcnumber2"#          Enter the Computer Names to be checked.
    $Monitored_Service = "EpicBCAService787","EpicPrintService787","EpicPullService787" #           Enter the service name to be checked.  Note this is the shorter name, not the longer "display name".  
    $verbose = 10 #                                                           What level of messages/counters do you wish to display? (0 = no counters, basic message 1 = counters only, 2= counters and full messages)   
    
################ Define variables and functions ################
if($Counters){[DOUBLE]$polymon = 1;$Status.StatusText = ""} else {[DOUBLE]$polymon = 0}
$Service_Status_Table = @{} ; $Service_Running_Error_displaytext = "" ; [DOUBLE]$ERRLVL = 1 ; $monitor_text_for_OK_condition= @();$monitor_text_for_alarm_condition = @()

function display_data{ 
if ($errlvl -gt 3){$errlvl = 3}  # No such thing as an errorlevel greater than 3   
switch($errlvl){ # Set the display message and counters based on the error level
    3   {$final_displaytext = "Monitor failure:   "+($monitor_text_for_alarm_condition| select -uniq);break} 
    2   {$final_displaytext = "Monitor warning:   "+($monitor_text_for_alarm_condition| select -uniq);break} 
    1   {$final_displaytext = "Monitor OK:  ";break}
default {$final_displaytext = "Monitor Failure:  Other Error:  ";break}}

if ($verbose -gt 1){$final_displaytext = ($final_displaytext)+($monitor_text_for_OK_condition)} # Add info text if $verbose is greater than 1
$displaymessage = ("   "+$final_displaytext) -replace "   ,", "" #remove unwanted commas, clean up the output string
Switch($polymon){
 1{$Status.StatusText=$displaymessage ; $Status.StatusID=$errlvl ;  if (($counter.length) -gt 1){$counter = $counter | select -uniq |sort-object ;  foreach ($count in $counter){$Counters.Add($count[0],$count[1])  }}}
 0{switch($errlvl){3{write-host  "Err LVL = FAIL: "$displaymessage} ;  2{write-host  "Err LVL = WARN: "$displaymessage} ; 1{write-host  "Err LVL = OK: "$displaymessage}}} }
}
                
################ Execute the Service Checks ################
foreach($pc in $Computernames){
$Service_Status_table[$pc]=0 #Build a hash table with each PC's value set in advance to "not running"
foreach($Retrieved_Status in (Get-Service -ComputerName $pc)) { 
foreach($Individual_service in $Monitored_Service){ if($Individual_service -match $Retrieved_Status.Name -and $Retrieved_Status.Status -eq 'Running') {
$Service_Status_table[$pc]+=1 }}} #If running service is found, then set the PC's value to "running"
}

$Service_Status_table.GetEnumerator() | % { # Go through the table and alert as appropriate
if (($_.value) -lt $Monitored_Service.count){  # If there are too few running services on any pc then:
  [DOUBLE]$ERRLVL += 1; #  raise the errorlevel indicator
  $monitor_text_for_alarm_condition +=  ", Some Service(s) not running for: "+($_.key) ; #enter a text entry for an alarm condition
  $Counter += ,@((($_.key)+': Some Service(s) not running'), 1)} # and create a $counter entry

  else {$monitor_text_for_OK_condition +=  ", Service(s) confirmed on "+($_.key) #If the pc service is running, then create informational text entry
  if ($verbose -gt 0){$Counter += ,@((($_.key)+': Services confirmed'), 1)}} # and if verbose is turned on, then create a $counter entry
}

display_data  # display the final findings
Aug 19, 2013 at 2:01 PM
Edited Aug 19, 2013 at 4:38 PM
Here's an improved version I finished up over the weekend. It posts an individual counter for the status of each process on each pc. That opens the door to having the action script restart any of the stopped processes.
    $ComputerNames = "pcnumber1","pcnumber2"#          Enter the Computer Names to be checked.
    $Monitored_Service = "EpicBCAService787","EpicPrintService787","EpicPullService787" #           Enter the service name to be checked.  Note this is the shorter name, not the longer "display name".
    $verbose = 2 #                                                           What level of messages/counters do you wish to display? ("0": , Basic message, no counters. "1": = , Basic message with counters. "2": Full messages with counters.)   
    
################ Define variables and functions ################
if($Counters){[DOUBLE]$polymon = 1;$Status.StatusText = ""} else {[DOUBLE]$polymon = 0}
$Service_Status_Table = @{} ; $Service_Running_Error_displaytext = "" ; [DOUBLE]$ERRLVL = 1 ; $monitor_text_for_OK_condition= @();$monitor_text_for_alarm_condition = @()

function display_data{ 
if ($errlvl -gt 3){$errlvl = 3}  # No such thing as an errorlevel greater than 3   
switch($errlvl){ # Set the display message and counters based on the error level
    3   {$final_displaytext = "Monitor failure:   "+($monitor_text_for_alarm_condition| select -uniq);break} 
    2   {$final_displaytext = "Monitor warning:   "+($monitor_text_for_alarm_condition| select -uniq);break} 
    1   {$final_displaytext = "Monitor OK:  ";break}
default {$final_displaytext = "Monitor Failure:  Other Error:  ";break}}

if ($verbose -gt 1){$final_displaytext = ($final_displaytext)+($monitor_text_for_OK_condition)} # Add info text if $verbose is greater than 1
$displaymessage = ("   "+$final_displaytext) -replace "   ,", "" #remove unwanted commas, clean up the output string
Switch($polymon){
 1{$Status.StatusText=$displaymessage ; $Status.StatusID=$errlvl ;  if (($counter.length) -gt 1){$counter = $counter | select -uniq |sort-object };  foreach ($count in $counter){$Counters.Add($count[0],$count[1])  }}
 0{switch($errlvl){3{write-host  "Err LVL = FAIL: "$displaymessage} ;  2{write-host  "Err LVL = WARN: "$displaymessage} ; 1{write-host  "Err LVL = OK: "$displaymessage}}} }
}
                
################ Execute the Service Checks ################
$Service_Status_table =@{}  #Build a hash table
foreach($pc in $Computernames){
$Service_Status_table[$pc] =@{}  #Populate the PC names
foreach($individual_service in $monitored_service){$Service_Status_table[$pc][$individual_service] = 0} #Populate the individual service names, with a zero "non-running" status
foreach($Retrieved_Status in (Get-Service -ComputerName $pc)) { #Go through the list of running services on each pc
foreach($Individual_service in $Monitored_Service){ if($Individual_service -match $Retrieved_Status.Name -and $Retrieved_Status.Status -eq 'Running') {
$Service_Status_table.$pc.$Individual_service = 1 }}} #If running service is found, then set that service's value to "running"

}
foreach($Individual_service in $Monitored_Service){ 
$Service_Status_table.GetEnumerator() | % { 
    if ($Service_Status_table.$($_.key).$Individual_service -ne 1){  # If any individual service is not running, then:
    [DOUBLE]$ERRLVL += 1; #  raise the errorlevel indicator
    $monitor_text_for_alarm_condition +=  ", "+$Individual_service+" Service not running for: "+$_.key ; #create a text entry for the error condition
    $Counter += ,@(($_.key+': '+$Individual_service+'Service NOT Running'), 0)} # and create a $counter entry

  else {$monitor_text_for_OK_condition +=  ", "+$Individual_service+"Service OK on "+$_.key #If the service IS running OK, then create informational text entry
  if ($verbose -gt 0){$Counter += ,@(($_.key+': '+$Individual_service+ ' Service OK'), 1)}} # and if verbose is turned on, then create a $counter entry
}}

display_data  # display the final findings.  The $verbose variable determines which error and informational text entries and counters will be displayed
And the action script to restart any stopped service:
if ($Status.StatusID -ge 2){
# $output_text = "" #for testing output

foreach ($list_item in $Counters){ 
if ($list_item.CounterValue -eq 0){
$output_text = $output_text + $list_item.Countername +" "
$output_text = $output_text + $list_item.CounterValue +" "

$server = $list_item.Countername.substring(0,$list_item.Countername.IndexOf(":"))
$output_text = $output_text + " " +$server

$Servicename = $list_item.Countername.substring($list_item.Countername.IndexOf(":")+2,$list_item.Countername.IndexOf("Service NOT")-10)

$output_text = $output_text + " " +$servicename
$startservice_error_return =  (Get-WmiObject -computer $server Win32_Service -Filter "Name='$($Servicename)'").InvokeMethod("StartService",$null)

$output_text = $output_text + " " +$startservice_error_return


# (Get-WmiObject -computer $server Win32_Service -Filter "Name='$($Servicename)'").InvokeMethod("StartService",$null)

}
}
# set-content -path C:\powershelltest.txt -value $output_text} #for testing output