How to Configure Windows Service Auto-Restart on Failure Using PowerShell


2 views

While the Windows Services GUI provides a convenient way to configure service recovery options, PowerShell offers more flexibility and automation capabilities for system administrators. The key cmdlet we'll be using is sc.exe (Service Control Manager) through PowerShell.

Here's the basic syntax to configure service recovery options:

sc.exe failure "ServiceName" reset= 30 actions= restart/60000

Where:

  • reset= 30 sets the failure counter reset period (in seconds)
  • actions= restart/60000 specifies the action (restart) and delay (60,000ms = 1 minute)

For a more robust solution, we can create a PowerShell function:

function Set-ServiceRecovery {
    param (
        [string]$ServiceName,
        [int]$ResetPeriod = 86400,
        [string]$FirstFailure = "restart/60000",
        [string]$SecondFailure = "restart/60000", 
        [string]$SubsequentFailures = "restart/60000",
        [string]$RebootMessage = ""
    )
    
    $actionList = "$FirstFailure/$SecondFailure/$SubsequentFailures"
    
    $scCommand = "sc.exe failure "$ServiceName" reset= $ResetPeriod actions= $actionList"
    if ($RebootMessage) {
        $scCommand += " command= "$RebootMessage""
    }
    
    Invoke-Expression $scCommand
}

# Example usage:
Set-ServiceRecovery -ServiceName "Spooler" -ResetPeriod 3600 -FirstFailure "restart/30000"

For more complex scenarios, we can use the FailureActionsFlag property via WMI:

$service = Get-WmiObject -Class Win32_Service -Filter "Name='Spooler'"
$service.Change(
    $null, $null, $null, $null, $null, $null, $null, $null,
    [uint32]2, # Sets the FailureActionsFlag to 2 (enables failure actions)
    $null, $null, $null
)

To check the current recovery settings:

sc.exe qfailure "Spooler"

Or using PowerShell:

Get-CimInstance -ClassName Win32_Service -Filter "Name='Spooler'" | 
    Select-Object Name, @{Name="FailureActions";Expression={$_.FailureActions}}

Basic configuration (restart after 1 minute on all failures):

sc.exe failure "Spooler" reset= 86400 actions= restart/60000/restart/60000/restart/60000

Progressive delays (increasing restart delays):

sc.exe failure "Spooler" reset= 3600 actions= restart/30000/restart/60000/restart/120000

Run a program on third failure:

sc.exe failure "Spooler" reset= 86400 actions= restart/30000/restart/60000/run/10000 command= "C:\Scripts\alert.exe"

Windows services often require automatic recovery mechanisms to maintain system stability. While the GUI method (services.msc → Properties → Recovery tab) is well-known, PowerShell provides superior automation capabilities for enterprise environments.

The primary command for managing service recovery is sc.exe, but we'll use PowerShell-native approaches where possible:

# View current recovery settings
Get-CimInstance -ClassName Win32_Service -Filter "Name='YourServiceName'" | 
Select-Object Name, @{Name="FailureActions";Expression={$_.FailureActions}}

Here's the complete PowerShell solution to configure auto-restart with escalating delays:

$serviceName = "YourServiceName"
$failureActions = @(
    @{
        Type = 1    # 1 = Restart service
        Delay = 60000  # 60 seconds delay (in milliseconds)
    },
    @{
        Type = 1
        Delay = 120000 # 120 seconds
    },
    @{
        Type = 1
        Delay = 300000 # 300 seconds
    }
)

$failureActionsBytes = $failureActions | ForEach-Object {
    [byte[]]@(
        $_.Type,
        $_.Delay -band 0xFF,
        ($_.Delay -shr 8) -band 0xFF,
        ($_.Delay -shr 16) -band 0xFF,
        ($_.Delay -shr 24) -band 0xFF
    )
}

$scParams = @{
    Name = $serviceName
    FailureActionsOnNonCrashFailures = $true
    FailureAction = $failureActionsBytes
    ResetPeriod = 86400 # Reset counter after 24 hours (seconds)
}

Set-Service @scParams -ErrorAction Stop

# Verify configuration
(Get-CimInstance -ClassName Win32_Service -Filter "Name='$serviceName'").FailureActions

For complex scenarios, consider these additional parameters:

# Set custom reboot message and failure command
$scFailureCommand = "C:\\Scripts\\ServiceFailureHandler.ps1"

sc.exe failure $serviceName reset= 86400 actions= restart/60000/restart/120000/restart/300000 command= "$scFailureCommand"

When deploying across multiple servers:

# Remote configuration example
$computers = "Server1","Server2","Server3"
$credential = Get-Credential

Invoke-Command -ComputerName $computers -Credential $credential -ScriptBlock {
    param($serviceName)
    sc.exe failure $serviceName reset= 86400 actions= restart/60000/restart/120000/restart/300000
} -ArgumentList $serviceName

If configurations don't apply:

  1. Verify service dependencies are properly configured
  2. Check Event Viewer for System logs (Event ID 7023, 7024)
  3. Ensure the account running the service has appropriate permissions