Services Management
Note
Query, start, stop, and configure Windows services with Get-Service, Start-Service, Stop-Service, and Restart-Service.
Overview
Windows services run in the background — think print spoolers, SQL Server instances, or your own scheduled agents. PowerShell's service cmdlets let you check status, control state, and inspect dependencies without opening services.msc. They're some of the most direct, no-surprises cmdlets in the whole language: Get-Service reads, Start/Stop/Restart-Service act.
Basic Syntax
Get-Service -Name "Spooler"
Start-Service -Name "Spooler"
Stop-Service -Name "Spooler"
Restart-Service -Name "Spooler"
Set-Service -Name "Spooler" -StartupType Automatic
Key Points
Get-Serviceworks on both the short service name (wuauserv) and display name (Windows Update)-Nameaccepts wildcards:Get-Service -Name "sql*"- Stopping a service with dependents fails unless you pass
-Force - Managing services on Windows requires an elevated (Administrator) PowerShell session
Querying Services
# All services
Get-Service
# Single service by name
Get-Service -Name "Spooler"
# Wildcard search
Get-Service -Name "sql*"
# Only running services
Get-Service | Where-Object { $_.Status -eq "Running" }
# Only stopped services that are set to auto-start (a common problem indicator)
Get-Service | Where-Object { $_.Status -eq "Stopped" -and $_.StartType -eq "Automatic" }
Output:
Status Name DisplayName
------ ---- -----------
Running Spooler Print Spooler
Stopped wuauserv Windows Update
Running W32Time Windows Time
Service Details
# Full property list, not just the default table
Get-Service -Name "Spooler" | Format-List *
# Startup type
Get-Service -Name "Spooler" | Select-Object Name, Status, StartType
# Service dependencies
$service = Get-Service -Name "Spooler"
$service.DependentServices # services that depend on this one
$service.ServicesDependedOn # services this one depends on
Starting, Stopping, and Restarting
# Start a stopped service
Start-Service -Name "Spooler"
# Stop a running service
Stop-Service -Name "Spooler"
# Stop a service even if other services depend on it
Stop-Service -Name "Spooler" -Force
# Restart (stop then start) in one call
Restart-Service -Name "Spooler"
# Preview before acting
Stop-Service -Name "Spooler" -WhatIf
Stopping a Service With Dependents
# BAD - fails if other services depend on this one
Stop-Service -Name "RpcSs"
# Error: Cannot stop service because other services depend on it
# GOOD - stop dependents too (use with caution)
Stop-Service -Name "RpcSs" -Force
-Force cascades the stop to every dependent service. Check DependentServices first so you know what else is about to go down. Bulk Operations
# Restart every service matching a pattern
Get-Service -Name "MSSQL*" | Restart-Service -Force
# Stop all services in a specific list
$servicesToStop = @("Spooler", "Fax", "WSearch")
Get-Service -Name $servicesToStop | Stop-Service -Force
# Report on a group of critical services
$criticalServices = @("Spooler", "WinRM", "W32Time")
Get-Service -Name $criticalServices | Select-Object Name, Status, StartType |
Format-Table -AutoSize
Configuring Startup Type
# Change startup type
Set-Service -Name "Spooler" -StartupType Automatic
Set-Service -Name "Fax" -StartupType Disabled
Set-Service -Name "WSearch" -StartupType Manual
# Change startup type and start it in the same operation
Set-Service -Name "Spooler" -StartupType Automatic -Status Running
StartupType Values
Automatic starts at boot. AutomaticDelayedStart (Windows Server / newer Windows) starts shortly after boot to reduce startup contention. Manual only starts when explicitly triggered or requested by another service. Disabled prevents it from starting at all, even manually, until re-enabled.
Remote Service Management
# Query a service on a remote computer
Get-Service -Name "Spooler" -ComputerName "SERVER01"
# Query across multiple computers
$computers = @("SERVER01", "SERVER02", "SERVER03")
Get-Service -Name "Spooler" -ComputerName $computers |
Select-Object MachineName, Name, Status
# Restart a service remotely with Invoke-Command (works even where -ComputerName is deprecated)
Invoke-Command -ComputerName "SERVER01" -ScriptBlock {
Restart-Service -Name "Spooler" -Force
}
Get-Service -ComputerName Is Being Phased Out
-ComputerName on Get-Service/Stop-Service/etc. only supports read/simple operations remotely and isn't available in all PowerShell 7+ contexts. For reliable remote control — especially anything that changes state — use Invoke-Command with PowerShell Remoting instead.
Important Parameters
| Parameter | Type | Description | Example |
|---|---|---|---|
-Name | String[] | Service name(s), supports wildcards | Get-Service -Name "sql*" |
-DisplayName | String | Filter by the friendly display name | Get-Service -DisplayName "Print*" |
-Force | Switch | Stop dependent services too | Stop-Service -Force |
-StartupType | String | Automatic, Manual, Disabled | Set-Service -StartupType Manual |
-Status | String | Set-Service: desired running state | Set-Service -Status Running |
-ComputerName | String[] | Query a remote machine (read-focused) | Get-Service -ComputerName "S1" |
-WhatIf | Switch | Preview the action | Stop-Service -WhatIf |
Common Patterns
# Pattern 1: Restart a service only if it's currently running
$svc = Get-Service -Name "Spooler"
if ($svc.Status -eq "Running") {
Restart-Service -Name "Spooler" -Force
}
# Pattern 2: Ensure a service is running and set to auto-start
$serviceName = "WinRM"
Set-Service -Name $serviceName -StartupType Automatic
if ((Get-Service -Name $serviceName).Status -ne "Running") {
Start-Service -Name $serviceName
}
# Pattern 3: Health check across a list of critical services
$critical = @("Spooler", "WinRM", "W32Time", "Dnscache")
Get-Service -Name $critical | ForEach-Object {
[PSCustomObject]@{
Service = $_.Name
Status = $_.Status
Healthy = ($_.Status -eq "Running")
}
}
Real-World Examples
Example: Service Health Check with Auto-Remediation
Scenario: Check a list of services that should always be running; restart any that have stopped and log what happened.
$requiredServices = @("Spooler", "WinRM", "W32Time")
$logPath = "C:\Logs\service-check.log"
foreach ($name in $requiredServices) {
$service = Get-Service -Name $name -ErrorAction SilentlyContinue
if (-not $service) {
Add-Content -Path $logPath -Value "$(Get-Date) - $name not found on this system"
continue
}
if ($service.Status -ne "Running") {
Add-Content -Path $logPath -Value "$(Get-Date) - $name was $($service.Status), restarting"
Start-Service -Name $name
}
}
Explanation: -ErrorAction SilentlyContinue handles services that don't exist on a given machine gracefully, and the log gives a clear audit trail of exactly what got restarted and when.
Tips & Tricks
Check DependentServices Before Stopping Anything
Reviewing what depends on a service before stopping it avoids the surprise of taking down half the OS because of one careless-Force. Service Names vs Display Names
# This works - short service name
Get-Service -Name "wuauserv"
# This does NOT work with -Name - that's the display name
Get-Service -Name "Windows Update" # fails, no match
# Use -DisplayName for the friendly name instead
Get-Service -DisplayName "Windows Update"
-Name matches the internal short name; -DisplayName matches what you see in services.msc. Mixing them up is a common source of "service not found" errors. Related Topics
- Process Management - Managing the processes services spawn
- Event Logs - Investigating why a service failed to start
- Scheduled Tasks - An alternative to services for periodic work