As a developer managing critical background processes, few things are more frustrating than discovering your Windows service has crashed overnight. Unlike desktop applications, services run unattended and need robust recovery mechanisms.
Windows actually includes built-in service recovery features that many developers overlook. Right-click your service in services.msc, go to Properties → Recovery tab. Here you can configure:
First failure: Restart the Service
Second failure: Restart the Service
Subsequent failures: Take No Action
Reset fail count after: 1 day
For more control, here's a PowerShell monitoring script that checks service status every 60 seconds:
# ServiceMonitor.ps1
$serviceName = "YourServiceName"
$checkInterval = 60 # seconds
while ($true) {
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($service -eq $null) {
Write-Host "Service $serviceName not found!" -ForegroundColor Red
break
}
if ($service.Status -ne "Running") {
Write-Host "$(Get-Date) - Service not running. Restarting..." -ForegroundColor Yellow
Start-Service -Name $serviceName
# Optional: Send email notification
# Send-MailMessage -To admin@yourdomain.com -From monitor@yourdomain.com -Subject "Service Restarted" -Body "Restarted $serviceName"
}
Start-Sleep -Seconds $checkInterval
}
To ensure your monitoring script runs continuously:
# Create scheduled task to run at startup
$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-File C:\Path\To\ServiceMonitor.ps1"
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DontStopOnIdleEnd -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
Register-ScheduledTask -TaskName "ServiceMonitor" -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest
The Windows SC (Service Control) utility offers another approach. Create a recovery.cmd file:
@echo off
:check
sc query "YourServiceName" | find "RUNNING"
if %ERRORLEVEL% == 1 (
sc start "YourServiceName"
timeout /t 10
)
timeout /t 60
goto check
For mission-critical services, consider creating a watchdog service:
// WatchdogService.cs
protected override void OnStart(string[] args)
{
ThreadPool.QueueUserWorkItem(state =>
{
while (true)
{
ServiceController sc = new ServiceController("TargetService");
if (sc.Status != ServiceControllerStatus.Running)
{
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
}
Thread.Sleep(60000);
}
});
}
Implement proper logging in your monitoring solution:
# Add to PowerShell script
$logPath = "C:\Logs\ServiceMonitor.log"
"[$(Get-Date)] Service status: $($service.Status)" | Out-File -FilePath $logPath -Append
Be mindful of monitoring frequency - every 60 seconds is usually sufficient. For services with strict uptime requirements, consider:
- Event log triggers instead of polling
- Windows Performance Monitor alerts
- Third-party monitoring tools like Nagios or Zabbix
Windows includes built-in service recovery options that can automatically restart failed services. Configure these settings through the Services management console:
sc failure "YourServiceName" reset= 60 actions= restart/60000
This configures the service to:
- Attempt a restart after 60 seconds (60000 milliseconds)
- Reset the failure counter after 60 seconds
For more control, create a PowerShell monitoring script:
# ServiceMonitor.ps1
$serviceName = "YourServiceName"
$sleepInterval = 30 # seconds
while ($true) {
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if ($service.Status -ne "Running") {
Start-Service -Name $serviceName
# Optional logging
Add-Content -Path "C:\logs\service_monitor.log" -Value "$(Get-Date) - Restarted $serviceName"
}
Start-Sleep -Seconds $sleepInterval
}
Schedule the PowerShell script to run continuously:
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\scripts\ServiceMonitor.ps1"
$trigger = New-ScheduledTaskTrigger -AtStartup
$settings = New-ScheduledTaskSettingsSet -StartWhenAvailable -DontStopOnIdleEnd -RestartInterval (New-TimeSpan -Minutes 1) -RestartCount 3
Register-ScheduledTask -TaskName "ServiceMonitor" -Action $action -Trigger $trigger -Settings $settings -RunLevel Highest
For mission-critical services, create a watchdog service in C#:
using System;
using System.ServiceProcess;
using System.Timers;
public class ServiceMonitor : ServiceBase
{
private Timer timer;
private const string TargetService = "YourServiceName";
protected override void OnStart(string[] args)
{
timer = new Timer(30000); // Check every 30 seconds
timer.Elapsed += CheckService;
timer.Start();
}
private void CheckService(object sender, ElapsedEventArgs e)
{
using (var sc = new ServiceController(TargetService))
{
if (sc.Status != ServiceControllerStatus.Running)
{
sc.Start();
sc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(30));
}
}
}
protected override void OnStop()
{
timer?.Stop();
timer?.Dispose();
}
}
Enhance your solution with proper logging and notifications:
# Enhanced PowerShell monitoring with email alerts
$serviceName = "YourServiceName"
$logPath = "C:\logs\service_monitor.log"
$smtpServer = "smtp.yourdomain.com"
$toEmail = "admin@yourdomain.com"
function Send-Alert {
param($message)
Send-MailMessage -From "monitor@yourdomain.com" -To $toEmail -Subject "Service Alert" -Body $message -SmtpServer $smtpServer
}
try {
$service = Get-Service -Name $serviceName
if ($service.Status -ne "Running") {
Start-Service -Name $serviceName
$logEntry = "$(Get-Date) - Restarted $serviceName"
Add-Content -Path $logPath -Value $logEntry
Send-Alert $logEntry
}
} catch {
$errorMsg = "$(Get-Date) - ERROR: $_"
Add-Content -Path $logPath -Value $errorMsg
Send-Alert $errorMsg
}