Introduction
In many enterprise environments, Windows services are critical to application availability. While Windows provides basic service recovery (restart on failure), it doesn’t tell you when something broke or what server needs attention.
This solution combines:
A service monitoring PowerShell script
A Teams adaptive card for rich notifications
A one-time setup script to configure Windows service recovery actions
Together, they provide automated detection, recovery, and alerting when key services stop.
Component Purpose
Service-Monitor.ps1
Actively checks service state and sends alerts
adaptive_card.json
Defines the Teams alert layout
setup-servicemonitoring.ps1
Configures Windows service recovery options
Each piece is intentionally separated to keep the solution modular and easy to maintain.
1. Service-Monitor.ps1 – Active Service Monitoring & Alerting
This script is responsible for:
Checking whether specific Windows services are running
Detecting stopped or failed services
Sending a structured alert to Microsoft Teams
Key Configuration Section
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$WebhookUrl = "<YOUR-TEAMS-WEBHOOK-URL>"
$services = @(
"AxInstSV" #service used to test
)
$jsonPath = Join-Path $PSScriptRoot "adaptive_card.json"
What this does:
- Forces TLS 1.2 (required for modern HTTPS endpoints)
- Defines the Teams webhook endpoint (replace with your own)
- Lists services to monitor
- Loads the adaptive card JSON template from disk
Adaptive Card Loading & Validation
if (-not (Test-Path $jsonPath)) {
Write-Error "adaptive_card.json not found"
exit
}
$jsonTemplate = Get-Content -Path $jsonPath -Raw
This ensures the alert template exists before monitoring begins, preventing silent failures.
Service State Checking Loop
The script iterates through each configured service:
foreach ($serviceName in $services) {
Write-Host "Checking $serviceName..." -NoNewline
}
Inside the loop (not shown in the excerpt), the script:
- Queries the service status
- Detects non-running states
- Injects real values (service name, server name, state)
- Sends the populated adaptive card to Teams
2. adaptive_card.json – Teams Alert Template
This JSON file defines how the alert appears in Teams.
Alert Header
{
"type": "TextBlock",
"text": "CRITICAL ALERT: ${service} Service Stopped",
"weight": "Bolder",
"size": "Large",
"color": "Attention"
}
This creates a bold, red, highly visible alert header
Contextual Information
{
"type": "FactSet",
"facts": [
{ "title": "Server Name", "value": "${serverName}" },
{ "title": "Service", "value": "${service}" }
]
}
This provides immediate operational context so responders know:
- Which server is impacted
- Which service requires attention
Human-Readable Description
{
"type": "TextBlock",
"text": "The ${service} service has failed and is in a ${state} state. Please remote onto ${serverName} to investigate.",
"wrap": true
}
This reduces guesswork and shortens incident response time.
3. setup-servicemonitoring.ps1 – Service Recovery Configuration
This is a one-time setup script that configures Windows service recovery actions.
Services to Configure
$Services = @(
'Spooler',
'W32Time'
#add/remove services as required.
)
Only services explicitly listed will be modified.
Recovery Behaviour Settings
$RestartDelayMs = 60000
$ResetAfterSeconds = 86400
- Restart service after 60 seconds
- Reset failure counter after 24 hours
Recovery Action Command
$ProgramPath = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
$ProgramParameters = '-executionpolicy bypass -windowstyle hidden -file "C:\Scripts\ServiceMonitoring\Service-Monitor.ps1"'
On service failure, Windows will:
- Attempt a service restart
- If failures persist, execute the monitoring script silently
- Trigger Teams notification
Applying Recovery Options
The function Set-ServiceRecoveryOptions uses sc.exe to configure:
- Failure actions
- Restart behaviour
- Command execution on failure
sc.exe failure "$ServiceName" reset= $ResetAfterSeconds actions= $actions command= "$fullRunCommand"
This directly modifies service configuration at the OS level.
Elevated Permissions Check
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Error "Please run this script as Administrator."
}
Service recovery settings require elevation, and this check prevents partial execution.
How Everything Fits Together
- Setup script configures Windows to react to service failures
- Windows Service Control Manager detects a failure
- Service recovery restarts and/or runs the monitor script
- Monitor script checks service state
- Adaptive card sends a rich Teams alert
This creates a self-healing, observable service monitoring pattern.
Deployment Tips
- Store all files in the same directory
- Test scripts manually before enabling recovery
- Start with non-production environments
- Document which services are monitored
Conclusion
This approach bridges the gap between automatic recovery and human visibility. By combining native Windows service recovery with PowerShell and Teams adaptive cards, you get faster detection, clearer alerts, and reduced mean time to resolution.
It’s lightweight, transparent, and easily extensible—ideal for application support and SRE-style operations.
All the files for this can be found on my github, here