Powershell script to remotely start services across a domain and email on failur

Hey guys, I’m still learning powershell and I’m working on developing a slightly more advanced script than what I’m used to working with, could use some help.

Basically this script needs to scan all servers on a domain for any “automatic” services that are in a “stopped” state, attempt to start them, and return an error code which will then be emailed to a case creation queue if the service fails to start. I have the following so far (No email config included, I can always add that later). Ideally I would also like to add an exclusion list that will skip over services with specific names (like the software protection service).

So far, this script seems to pull the CSV correctly, try is working correctly, and it successfully cycles through each server, ultimately presenting the following output:

Updated Server list has been pulled from AD and sent to C:\Patching\ObjectList.csv
Press Enter to continue…:
Attempting to start the Print Spooler service on ASHDC01
0
Successfully started ‘Print Spooler’ on ASHDC01
Attempting to start the Software Protection service on ASHDC01
Set-Service : Service ‘Software Protection (sppsvc)’ cannot be configured due to the following error: Access is denied
At C:\Users\jesse\Desktop\ServiceCheck.ps1:58 char:84

  • … e $Name.name | Set-Service -Status Running
  •                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : PermissionDenied: (System.ServiceProcess.ServiceController:ServiceController) [Set-Service], ServiceCommandException
    • FullyQualifiedErrorId : CouldNotSetService,Microsoft.PowerShell.Commands.SetServiceCommand

0
Successfully started ‘Software Protection’ on ASHDC01
Attempting to start the Software Protection service on ASHVC01
Set-Service : Service ‘Software Protection (sppsvc)’ cannot be configured due to the following error: Access is denied
At C:\Users\jesse\Desktop\ServiceCheck.ps1:58 char:84

  • … e $Name.name | Set-Service -Status Running
  •                ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    • CategoryInfo : PermissionDenied: (System.ServiceProcess.ServiceController:ServiceController) [Set-Service], ServiceCommandException
    • FullyQualifiedErrorId : CouldNotSetService,Microsoft.PowerShell.Commands.SetServiceCommand

0
Successfully started ‘Software Protection’ on ASHVC01

This has a few issues right off the bat, A: the error code for access denied should be “2”, not 0-- so the switch command doesn’t appear to be correctly displaying the output. The software protection service also doesn’t exist on ASHVC01 so it isn’t correctly scanning for stopped services on the new server but simply seems to be using the services that didn’t start on the first server for the second (I’m saying this because I stopped the print spooler on the ashvc01 server also and it didn’t attempt to start). Any help would be greatly appreciated.

Import-Module ActiveDirectory

## Return Code Listing
$ReturnCode = @{}
$ReturnCode.Add(0,"Success")
$ReturnCode.Add(1,"Not Supported")
$ReturnCode.Add(2,"Access Denied")
$ReturnCode.Add(3,"Dependent Services Running")
$ReturnCode.Add(4,"Invalid Service Control")
$ReturnCode.Add(5,"Service Cannot Accept Control")
$ReturnCode.Add(6,"Service Not Active")
$ReturnCode.Add(7,"Service Request Timeout")
$ReturnCode.Add(8,"Unknown Failure")
$ReturnCode.Add(9,"Path Not Found")
$ReturnCode.Add(10,"Service Already Running")
$ReturnCode.Add(11,"Service Database Locked")
$ReturnCode.Add(12,"Service Dependency Deleted")
$ReturnCode.Add(13,"Service Dependency Failure")
$ReturnCode.Add(14,"Service Disabled")
$ReturnCode.Add(15,"Service Logon Failure")
$ReturnCode.Add(16,"Service Marked For Deletion")
$ReturnCode.Add(17,"Service No Thread")
$ReturnCode.Add(18,"Status Circular Dependency")
$ReturnCode.Add(19,"Status Duplicate Name")
$ReturnCode.Add(20,"Status Invalid Name")
$ReturnCode.Add(21,"Status Invalid Parameter")
$ReturnCode.Add(22,"Status Invalid Service Account")
$ReturnCode.Add(23,"Status Service Exists")
$ReturnCode.Add(24,"Service Already Paused")

##Defines Output files needed for listing each server in the environment

$outputfile = "C:\Patching\ObjectList.csv"
$servicelist = "C:\Patching\ServiceList.csv"
$Class = @{
Class = "Win32_Service"
}
$FindFilter = @{
Filter = "startmode='auto' and state='Stopped'"
}

##Pull all "Server" Operating system PCs from Active Directory and export to the defined outputfile.

Get-ADComputer -Filter {OperatingSystem -Like "Windows *Server*"} -Property * | select Name | Export-CSV -path $outputfile -force -notype
write-host "Updated Server list has been pulled from AD and sent to" $outputfile

Pause 10

##Define the Servers object for the next foreach
$computername = Import-CSV $outputfile

try{
foreach ($name in $computername){

          Foreach($Svc in Get-WmiObject @Class @FindFilter){
          Write-Host "Attempting to start the"$Svc.DisplayName"service on "$Name.name -ForeGround "Yellow"
          $Command = Get-Service -Name $Svc.DisplayName -Computername $Name.name | Set-Service -Status Running
         [int32]$Result = $Command.ReturnValue
          $Result

switch ($Result){
0 {Write-Output "Successfully started '$($Svc.DisplayName)' on $($Name.name)"; break}
default {Write-Error -Message "Error starting '$($Svc.DisplayName)' on $($Svc.__SERVER). Error: $($ReturnCode[$Result])."}
}
}}}
catch{
Write-Error "Error trying to connect and retrieve services from $Name.name"
}

I don’t have time to completely look over your code today, but I think you need to move your Try/Catch code inside the Foreach. That way for each system, it tries/catches. Probably most of your problem.

Brian