Microsoft KMS ServerRole Service Recovery

Microsoft.KMS.ServerRole.Service.Recovery (Recovery)

Element properties:

TargetMicrosoft.KMS.ServerRole
MonitorMicrosoft.KMS.ServerRole.Service.Monitor
Reset MonitorFalse
RemotableTrue
Timeout300
CategoryCustom
Enabledfalse
AccessibilityPublic

Member Modules:

ID Module Type TypeId RunAs 
PSWA WriteAction Microsoft.Windows.PowerShellWriteAction Default

Source Code:

<Recovery ID="Microsoft.KMS.ServerRole.Service.Recovery" Accessibility="Public" Enabled="false" Target="Microsoft.KMS.ServerRole" Monitor="Microsoft.KMS.ServerRole.Service.Monitor" ResetMonitor="false" ExecuteOnState="Warning" Remotable="true" Timeout="300">
<Category>Custom</Category>
<WriteAction ID="PSWA" TypeID="Windows!Microsoft.Windows.PowerShellWriteAction">
<ScriptName>Microsoft.KMS.ServerRole.Service.Recovery.ps1</ScriptName>
<ScriptBody><Script>
#=================================================================================
# Script to restart a service
#
# Author: Kevin Holman
#
# Version: 1.0
#
#=================================================================================


# Manual Testing section - put stuff here for manually testing script - typically parameters:
#=================================================================================
# $ServiceName = "spooler"
#=================================================================================


# Constants section - modify stuff here:
#=================================================================================
# Assign script name variable for use in event logging
$ScriptName = "Microsoft.KMS.ServerRole.Service.Recovery.ps1"
$EventID = "3750"
#=================================================================================


# Starting Script section
#=================================================================================
# Gather the start time of the script
$StartTime = Get-Date
#Set variable to be used in logging events
$whoami = whoami
# Load MOMScript API
$momapi = New-Object -comObject MOM.ScriptAPI
#=================================================================================


# Begin MAIN script section
#=================================================================================

[string]$ServiceName = "##ServiceName##"

#Log script event that we are starting task
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Recovery script for service: ($ServiceName) is starting. `n Running as ($whoami).")
write-host "Recovery script for service: ($ServiceName) is starting. Running as ($whoami)."

#Get the service object
$Svc = Get-Service $ServiceName

#Check to ensure the service exists:
IF (!$Svc)
{
$momapi.LogScriptEvent($ScriptName,3751,2, "`n Service ($ServiceName) was not found on this computer. `n This indicates a misconfiguration of the monitor. `n Error is ($error)")
write-host "Service ($ServiceName) was not found on this computer. This indicates a misconfiguration of the monitor. Error is ($error)"
EXIT
}

#Get Service Status:
[string]$SvcStatus = $Svc.Status

#Do not continue is service is already running
IF ($SvcStatus -eq "Running")
{
$momapi.LogScriptEvent($ScriptName,3752,2, "`n Service ($ServiceName) was found to be in the Running state. `n This indicates a misconfiguration of the monitor. `n No recovery action will be taken.")
write-host "Service ($ServiceName) was found to be in the Running state. This indicates a misconfiguration of the monitor. No recovery action will be taken."
EXIT
}

#Log recovery information event
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Service: ($ServiceName) was found to be in the ($SvcStatus) state. Recovery will be attempted.")
write-host "Service: ($ServiceName) was found to be in the ($SvcStatus) state. Recovery will be attempted."

#Attempt First Recovery
Restart-Service -Name $ServiceName -Force
#Wait time in seconds
Start-Sleep 20
#Get the service object
$Svc = Get-Service $ServiceName
#Get Service Status:
$SvcStatus = $Svc.Status

IF ($SvcStatus -ne "Running")
{
#Attempt Second Recovery
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Service: ($ServiceName) second attempt at recovering starting now.")
write-host "Service: ($ServiceName) second attempt at recovering starting now."
Restart-Service -Name $ServiceName -Force
Start-Sleep 20
$Svc = Get-Service $ServiceName
$SvcStatus = $Svc.Status
}

IF ($SvcStatus -ne "Running")
{
#Attempt Third Recovery
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Service: ($ServiceName) third attempt at recovering starting now.")
write-host "Service: ($ServiceName) third attempt at recovering starting now."
Restart-Service -Name $ServiceName -Force
Start-Sleep 20
$Svc = Get-Service $ServiceName
$SvcStatus = $Svc.Status
}

IF ($SvcStatus -eq "Running")
{
#Log event of a successful restart
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Service: ($ServiceName) was successfully restarted and then detected to be in the Running state.")
write-host "Service: ($ServiceName) was successfully restarted and then detected to be in the Running state."
}
ELSE
{
#Log event of a successful restart
$momapi.LogScriptEvent($ScriptName,3753,2,"`n Service: ($ServiceName) is not running. `n Recovery was attempted and failed. `n Manual interventon is required. `n The last detected service status was ($SvcStatus).")
write-host "Service: ($ServiceName) is not running. Recovery was attempted and failed. Manual interventon is required. The last detected service status was ($SvcStatus)."
}

# Check to see if this recovery script has been run multiple times in the last x minutes for detection of too many recovery actions
$Message = "*($ServiceName) is starting*"
$Events = Get-EventLog -LogName 'Operations Manager' -After $StartTime.AddMinutes(-60) -Message $Message | where {$_.EventID -eq 3750}
$EventCount = $Events.Count
IF ($EventCount -ge 3)
{
$momapi.LogScriptEvent($ScriptName,3754,2,"`n Too many service recoveries have been attempted for ($ServiceName). `n ($EventCount) recoveries are detected in the event log. `n Manual interventon is required.")
write-host "Too many service recoveries have been attempted for ($ServiceName). ($EventCount) recoveries are detected in the event log. Manual interventon is required."
}

# End of script section
#=================================================================================
#Log an event for script ending and total execution time.
$EndTime = Get-Date
$ScriptTime = ($EndTime - $StartTime).TotalSeconds
$momapi.LogScriptEvent($ScriptName,$EventID,0,"`n Script Completed. `n Script Runtime: ($ScriptTime) seconds.")
write-host "Script Completed. Script Runtime: ($ScriptTime) seconds."
#=================================================================================
# End of script
</Script></ScriptBody>
<TimeoutSeconds>240</TimeoutSeconds>
</WriteAction>
</Recovery>