Windows Service Management
Comprehensive guide to checking, monitoring, and managing Windows services with PowerShell.
Basic Service Status Commands​
1. Check Service Status​
Single service:
Get-Service -Name "ddagent"
Multiple services:
Get-Service -Name "ddagent", "W3SVC", "MSSQLSERVER"
With detailed properties:
Get-Service -Name "ddagent" | Select-Object Name, DisplayName, Status, StartType, ServiceType
Output shows:
- Service name
- Display name
- Current status (Running, Stopped, etc.)
- Startup type (Automatic, Manual, Disabled)
- Service type
2. Check Service Startup Type​
Get-Service -Name "ddagent" | Select-Object Name, StartType
Check if service is set to automatic:
(Get-Service -Name "ddagent").StartType -eq "Automatic"
3. List All Services​
Get-Service
With formatted output:
Get-Service | Format-Table Name, DisplayName, Status, StartType -AutoSize
4. List Running Services​
Get-Service | Where-Object { $_.Status -eq 'Running' }
Count running services:
(Get-Service | Where-Object { $_.Status -eq 'Running' }).Count
Export to CSV:
Get-Service | Where-Object { $_.Status -eq 'Running' } | Export-Csv -Path "C:\Reports\running-services.csv" -NoTypeInformation
5. List Stopped Services​
Get-Service | Where-Object { $_.Status -eq 'Stopped' }
Stopped services that are set to automatic:
Get-Service | Where-Object { $_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic' }
6. List Services by Pattern​
Find services with "data" in name:
Get-Service | Where-Object { $_.Name -like '*data*' }
Find services with "SQL" in display name:
Get-Service | Where-Object { $_.DisplayName -like '*SQL*' }
Service Control Commands​
7. Start Service​
Start-Service -Name "ddagent"
Start and wait:
Start-Service -Name "ddagent" -PassThru
Start multiple services:
Start-Service -Name "ddagent", "W3SVC", "MSSQLSERVER"
8. Stop Service​
Stop-Service -Name "ddagent"
Force stop:
Stop-Service -Name "ddagent" -Force
Stop and wait for dependent services:
Stop-Service -Name "W3SVC" -Force -PassThru | Wait-Service
9. Restart Service​
Restart-Service -Name "ddagent"
Restart with force:
Restart-Service -Name "ddagent" -Force
Restart and display status:
Restart-Service -Name "ddagent" -PassThru | Select-Object Name, Status
10. Suspend/Resume Service​
Suspend (pause) service:
Suspend-Service -Name "Spooler"
Resume service:
Resume-Service -Name "Spooler"
Service Configuration​
11. Set Service Startup Type​
Set to Automatic:
Set-Service -Name "ddagent" -StartupType Automatic
Set to Manual:
Set-Service -Name "ddagent" -StartupType Manual
Set to Disabled:
Set-Service -Name "ddagent" -StartupType Disabled
Set to Automatic (Delayed Start):
Set-Service -Name "ddagent" -StartupType AutomaticDelayedStart
12. Change Service Display Name​
Set-Service -Name "ddagent" -DisplayName "Datadog Agent Service"
13. Change Service Description​
Set-Service -Name "ddagent" -Description "Datadog monitoring agent for system and application metrics"
14. Configure Service Recovery Options​
Using sc.exe command:
# Restart service on failure
sc.exe failure ddagent reset= 86400 actions= restart/60000/restart/60000/restart/60000
Set recovery to restart after 1 minute:
sc.exe failure ddagent actions= restart/60000
Service Dependencies​
15. View Service Dependencies​
Get-Service -Name "W3SVC" | Select-Object -ExpandProperty DependentServices
View services this service depends on:
Get-Service -Name "W3SVC" | Select-Object -ExpandProperty ServicesDependedOn
Full dependency tree:
$service = Get-Service -Name "W3SVC"
Write-Host "Services $($service.Name) depends on:" -ForegroundColor Cyan
$service.ServicesDependedOn | Select-Object Name, Status
Write-Host "`nServices that depend on $($service.Name):" -ForegroundColor Cyan
$service.DependentServices | Select-Object Name, Status
16. Check if Service Has Dependencies​
$service = Get-Service -Name "W3SVC"
if ($service.DependentServices.Count -gt 0) {
Write-Host "$($service.Name) has $($service.DependentServices.Count) dependent services"
$service.DependentServices | Select-Object Name, Status
}
Service Monitoring​
17. Monitor Service Status​
Watch service status (refresh every 5 seconds):
while ($true) {
Clear-Host
Get-Service -Name "ddagent" | Select-Object Name, Status, StartType
Start-Sleep -Seconds 5
}
18. Alert on Service Status Change​
$serviceName = "ddagent"
$lastStatus = (Get-Service -Name $serviceName).Status
while ($true) {
$currentStatus = (Get-Service -Name $serviceName).Status
if ($currentStatus -ne $lastStatus) {
Write-Host "[$((Get-Date).ToString('yyyy-MM-dd HH:mm:ss'))] Service $serviceName changed from $lastStatus to $currentStatus" -ForegroundColor Yellow
$lastStatus = $currentStatus
}
Start-Sleep -Seconds 10
}
19. Check Service Uptime​
Using WMI:
$service = Get-WmiObject Win32_Service -Filter "Name='ddagent'"
$process = Get-Process -Id $service.ProcessId -ErrorAction SilentlyContinue
if ($process) {
$uptime = (Get-Date) - $process.StartTime
Write-Host "Service $($service.Name) uptime: $($uptime.Days) days, $($uptime.Hours) hours, $($uptime.Minutes) minutes"
}
20. Monitor Multiple Services​
$services = @('ddagent', 'W3SVC', 'MSSQLSERVER')
while ($true) {
Clear-Host
Write-Host "Service Status Monitor - $(Get-Date)" -ForegroundColor Cyan
Write-Host "="*60
foreach ($svc in $services) {
$status = (Get-Service -Name $svc -ErrorAction SilentlyContinue).Status
$color = if ($status -eq 'Running') { 'Green' } else { 'Red' }
Write-Host "$svc`: $status" -ForegroundColor $color
}
Start-Sleep -Seconds 5
}
Advanced Service Queries​
21. Get Service Account Information​
Get-WmiObject Win32_Service -Filter "Name='ddagent'" | Select-Object Name, StartName, State, StartMode
All services and their accounts:
Get-WmiObject Win32_Service | Select-Object Name, DisplayName, StartName, State | Sort-Object StartName | Format-Table -AutoSize
22. Find Services Running as Specific Account​
Get-WmiObject Win32_Service | Where-Object { $_.StartName -like '*LocalSystem*' } | Select-Object Name, DisplayName, State
Find services running as domain account:
Get-WmiObject Win32_Service | Where-Object { $_.StartName -like 'DOMAIN\*' } | Select-Object Name, DisplayName, StartName, State
23. Get Service Path and Binary​
Get-WmiObject Win32_Service -Filter "Name='ddagent'" | Select-Object Name, PathName
Get process ID and executable:
Get-WmiObject Win32_Service -Filter "Name='ddagent'" | Select-Object Name, ProcessId, PathName
24. Check Service Performance Metrics​
Get process info for service:
$service = Get-WmiObject Win32_Service -Filter "Name='ddagent'"
if ($service.ProcessId -gt 0) {
Get-Process -Id $service.ProcessId | Select-Object Name, CPU, @{Name="Memory(MB)";Expression={[math]::Round($_.WorkingSet/1MB,2)}}, StartTime
}
Service Troubleshooting​
25. Find Services That Failed to Start​
Get-EventLog -LogName System -Source "Service Control Manager" -EntryType Error -Newest 50 | Where-Object { $_.Message -like '*failed to start*' } | Select-Object TimeGenerated, Message
Using Get-WinEvent:
Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Service Control Manager'; Level=2} -MaxEvents 50 | Where-Object { $_.Message -like '*failed*' }
26. View Service Event Logs​
Get-EventLog -LogName Application -Source "Datadog Agent" -Newest 20 | Select-Object TimeGenerated, EntryType, Message
Filter by entry type:
Get-EventLog -LogName Application -Source "Datadog Agent" -EntryType Error -Newest 20
27. Check Service Start Failures​
$serviceName = "ddagent"
Get-EventLog -LogName System | Where-Object {
$_.Source -eq "Service Control Manager" -and
$_.Message -like "*$serviceName*" -and
$_.EntryType -eq "Error"
} | Select-Object -First 10 TimeGenerated, Message
28. Test Service Restart​
$serviceName = "ddagent"
$service = Get-Service -Name $serviceName
Write-Host "Testing restart of $serviceName..." -ForegroundColor Cyan
# Stop
Write-Host "Stopping service..."
Stop-Service -Name $serviceName -Force
Start-Sleep -Seconds 2
# Verify stopped
$status = (Get-Service -Name $serviceName).Status
Write-Host "Status after stop: $status" -ForegroundColor $(if ($status -eq 'Stopped') { 'Green' } else { 'Red' })
# Start
Write-Host "Starting service..."
Start-Service -Name $serviceName
Start-Sleep -Seconds 2
# Verify running
$status = (Get-Service -Name $serviceName).Status
Write-Host "Status after start: $status" -ForegroundColor $(if ($status -eq 'Running') { 'Green' } else { 'Red' })
Bulk Operations​
29. Start All Stopped Automatic Services​
Get-Service | Where-Object { $_.StartType -eq 'Automatic' -and $_.Status -eq 'Stopped' } | ForEach-Object {
Write-Host "Starting $($_.Name)..." -ForegroundColor Yellow
Start-Service -Name $_.Name -ErrorAction SilentlyContinue
}
30. Stop All Non-Essential Services​
$essentialServices = @('Winmgmt', 'RpcSs', 'SENS', 'EventLog')
$nonEssentialRunning = Get-Service | Where-Object {
$_.Status -eq 'Running' -and
$_.StartType -eq 'Manual' -and
$essentialServices -notcontains $_.Name
}
foreach ($service in $nonEssentialRunning) {
Write-Host "Stopping $($service.Name)..." -ForegroundColor Yellow
Stop-Service -Name $service.Name -Force -ErrorAction SilentlyContinue
}
31. Export Service Configuration​
Get-Service | Select-Object Name, DisplayName, Status, StartType | Export-Csv -Path "C:\Backup\services-config-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
Include detailed information:
Get-WmiObject Win32_Service | Select-Object Name, DisplayName, StartName, State, StartMode, PathName | Export-Csv -Path "C:\Backup\services-detailed-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
32. Compare Service States​
Save current state:
Get-Service | Select-Object Name, Status, StartType | Export-Csv -Path "C:\Baseline\services-baseline.csv" -NoTypeInformation
Compare with baseline:
$baseline = Import-Csv -Path "C:\Baseline\services-baseline.csv"
$current = Get-Service | Select-Object Name, Status, StartType
foreach ($base in $baseline) {
$curr = $current | Where-Object { $_.Name -eq $base.Name }
if ($curr.Status -ne $base.Status -or $curr.StartType -ne $base.StartType) {
Write-Host "Changed: $($base.Name) - Status: $($base.Status)->$($curr.Status), StartType: $($base.StartType)->$($curr.StartType)" -ForegroundColor Yellow
}
}
Service Creation and Removal​
33. Create New Service​
Using sc.exe:
sc.exe create MyService binPath= "C:\MyApp\service.exe" start= auto DisplayName= "My Custom Service"
Using New-Service (PowerShell 6+):
New-Service -Name "MyService" -BinaryPathName "C:\MyApp\service.exe" -DisplayName "My Custom Service" -StartupType Automatic -Description "My service description"
34. Remove Service​
sc.exe delete MyService
Stop and remove:
Stop-Service -Name "MyService" -Force
sc.exe delete MyService
Scheduled Service Monitoring​
35. Create Service Monitor Task​
# Create monitoring script
$monitorScript = @'
$serviceName = "ddagent"
$service = Get-Service -Name $serviceName
if ($service.Status -ne 'Running') {
Start-Service -Name $serviceName
$message = "Service $serviceName was stopped and has been restarted at $(Get-Date)"
$message | Add-Content "C:\Logs\service-monitor.log"
# Optionally send email alert
# Send-MailMessage -To "admin@domain.com" -From "monitor@domain.com" -Subject "Service Alert" -Body $message -SmtpServer "smtp.domain.com"
}
'@
Set-Content -Path "C:\Scripts\monitor-service.ps1" -Value $monitorScript
# Create scheduled task
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -File C:\Scripts\monitor-service.ps1"
$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Days 365)
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount
Register-ScheduledTask -TaskName "ServiceMonitor" -Action $action -Trigger $trigger -Principal $principal
Service Health Reports​
36. Generate Service Health Report​
$report = @"
=== SERVICE HEALTH REPORT ===
Generated: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')
RUNNING SERVICES: $((Get-Service | Where-Object { $_.Status -eq 'Running' }).Count)
STOPPED SERVICES: $((Get-Service | Where-Object { $_.Status -eq 'Stopped' }).Count)
AUTOMATIC SERVICES NOT RUNNING:
$((Get-Service | Where-Object { $_.StartType -eq 'Automatic' -and $_.Status -ne 'Running' } | Select-Object Name, DisplayName, Status | Format-Table | Out-String))
CRITICAL SERVICES STATUS:
$((Get-Service -Name 'ddagent', 'W3SVC', 'MSSQLSERVER' -ErrorAction SilentlyContinue | Select-Object Name, Status, StartType | Format-Table | Out-String))
RECENT SERVICE ERRORS (Last 24 hours):
$((Get-EventLog -LogName System -Source "Service Control Manager" -EntryType Error -After (Get-Date).AddDays(-1) | Select-Object -First 10 TimeGenerated, Message | Format-List | Out-String))
"@
$report | Out-File "C:\Reports\service-health-$(Get-Date -Format 'yyyyMMdd-HHmmss').txt"
Write-Host $report
37. Service Availability Check​
$criticalServices = @('ddagent', 'W3SVC', 'MSSQLSERVER')
$allRunning = $true
Write-Host "`n=== Critical Services Check ===" -ForegroundColor Cyan
foreach ($svcName in $criticalServices) {
$service = Get-Service -Name $svcName -ErrorAction SilentlyContinue
if ($service) {
$status = $service.Status
$color = if ($status -eq 'Running') { 'Green' } else { 'Red'; $allRunning = $false }
Write-Host "$svcName`: $status" -ForegroundColor $color
} else {
Write-Host "$svcName`: NOT INSTALLED" -ForegroundColor Red
$allRunning = $false
}
}
Write-Host "`nOverall Status: " -NoNewline
if ($allRunning) {
Write-Host "ALL SERVICES RUNNING" -ForegroundColor Green
} else {
Write-Host "SOME SERVICES NOT RUNNING" -ForegroundColor Red
}
Remote Service Management​
38. Manage Services on Remote Computer​
$computer = "SERVER01"
Get-Service -ComputerName $computer -Name "ddagent"
Start remote service:
Get-Service -ComputerName $computer -Name "ddagent" | Start-Service
Using Invoke-Command:
Invoke-Command -ComputerName SERVER01 -ScriptBlock {
Get-Service -Name "ddagent" | Restart-Service
}
39. Query Services on Multiple Computers​
$computers = @('SERVER01', 'SERVER02', 'SERVER03')
$serviceName = "ddagent"
foreach ($computer in $computers) {
Write-Host "`nChecking $computer..." -ForegroundColor Cyan
Get-Service -ComputerName $computer -Name $serviceName -ErrorAction SilentlyContinue | Select-Object MachineName, Name, Status, StartType
}
Parallel execution:
$computers = @('SERVER01', 'SERVER02', 'SERVER03')
$serviceName = "ddagent"
Invoke-Command -ComputerName $computers -ScriptBlock {
param($svcName)
Get-Service -Name $svcName | Select-Object MachineName, Name, Status, StartType
} -ArgumentList $serviceName
40. Remote Service Report​
$computers = @('SERVER01', 'SERVER02', 'SERVER03')
$results = foreach ($computer in $computers) {
try {
$services = Get-Service -ComputerName $computer -ErrorAction Stop
[PSCustomObject]@{
Computer = $computer
TotalServices = $services.Count
Running = ($services | Where-Object { $_.Status -eq 'Running' }).Count
Stopped = ($services | Where-Object { $_.Status -eq 'Stopped' }).Count
AutoNotRunning = ($services | Where-Object { $_.StartType -eq 'Automatic' -and $_.Status -ne 'Running' }).Count
Status = 'Online'
}
} catch {
[PSCustomObject]@{
Computer = $computer
TotalServices = 0
Running = 0
Stopped = 0
AutoNotRunning = 0
Status = 'Offline'
}
}
}
$results | Format-Table -AutoSize
$results | Export-Csv -Path "C:\Reports\remote-services-$(Get-Date -Format 'yyyyMMdd').csv" -NoTypeInformation
Quick Reference​
Common Service Commands​
# Status
Get-Service -Name "servicename"
# Start/Stop/Restart
Start-Service -Name "servicename"
Stop-Service -Name "servicename" -Force
Restart-Service -Name "servicename"
# Configuration
Set-Service -Name "servicename" -StartupType Automatic
Set-Service -Name "servicename" -Description "Service description"
# Monitoring
Get-Service | Where-Object { $_.Status -eq 'Running' }
Get-Service | Where-Object { $_.StartType -eq 'Automatic' -and $_.Status -ne 'Running' }
# Dependencies
Get-Service -Name "servicename" | Select-Object -ExpandProperty DependentServices
Get-Service -Name "servicename" | Select-Object -ExpandProperty ServicesDependedOn
# WMI Queries
Get-WmiObject Win32_Service -Filter "Name='servicename'"
Get-WmiObject Win32_Service | Select-Object Name, StartName, State, StartMode