Get-Service in PowerShell: Auditing Windows Services

Get-Service in PowerShell: Auditing Windows Services

You open Event Viewer after a rough night and find application errors nobody saw happen. The cause? A service that should have been running had been stopped for hours. Get-Service in PowerShell is the tool that solves this diagnosis in seconds — and keeps you from finding out about the problem from a customer.

What Get-Service Is and When to Use It

Get-Service is a native PowerShell cmdlet that returns objects representing the services installed on Windows. Each object carries properties like Name, DisplayName, Status and StartType — enough information to build audits, alerts and automated remediation scripts.

No extra module needed. It works in PowerShell 5.1 (native on Windows 10/11) and PowerShell 7.x. It's the natural next step after learning to audit local accounts with Get-LocalUser.

Listing All Services

Without parameters, the cmdlet returns every service on the machine:

Get-Service

The default output shows Status, Name and DisplayName. To see every available field:

Get-Service | Select-Object *

To look up a specific service by name:

Get-Service -Name "wuauserv"   # Windows Update

It accepts wildcards, which helps a lot when you only know part of the name:

Get-Service -Name "sql*"       # everything starting with sql

Filtering Services by Status

Combining it with Where-Object is where the cmdlet becomes genuinely useful:

# Running services only
Get-Service | Where-Object { $_.Status -eq "Running" }

# Stopped services only
Get-Service | Where-Object { $_.Status -eq "Stopped" }

To sort by status and get a quick view of what's stopped:

Get-Service | Sort-Object Status | Format-Table -AutoSize

How Do You Identify Automatic Services That Have Stopped?

Use the combined Status and StartType filter — it's the most useful diagnostic after a problem boot:

Get-Service | Where-Object { $_.Status -eq "Stopped" -and $_.StartType -eq "Automatic" }

Services set to start automatically but currently stopped point to a crash, a failing dependency, or misconfiguration. Any of those scenarios needs attention before it turns into an incident.

Starting, Stopping and Restarting Services

Get-Service returns objects you can pipe straight into the control cmdlets:

# Start a stopped service
Start-Service -Name "Spooler"

# Stop it
Stop-Service -Name "Spooler"

# Restart (stops then starts in sequence)
Restart-Service -Name "Spooler"

To restart every stopped automatic service — useful in recovery scripts:

Get-Service |
  Where-Object { $_.Status -eq "Stopped" -and $_.StartType -eq "Automatic" } |
  Start-Service

Use this with care: some services stay stopped by design (demand-start services, for instance). Review the list before running Start-Service in bulk.

Exporting a Service Inventory

To generate a report and keep it as a reference baseline:

Get-Service | Select-Object Name, DisplayName, Status, StartType |
  Export-Csv -Path "C:\Audit\services-$(Get-Date -Format 'yyyy-MM-dd').csv" -NoTypeInformation -Encoding UTF8

Comparing that CSV across different dates reveals newly installed services (malware occasionally installs itself as a Windows service) or services that vanished after a problematic update. It's a simple baseline that complements PowerShell's audit logs.

Checking Service Dependencies

When a service won't come up, it may depend on another one that failed first. To inspect the chain:

# What this service needs in order to run
(Get-Service -Name "Spooler").RequiredServices

# Who depends on this service
(Get-Service -Name "RpcSs").DependentServices

Understanding the dependencies speeds up diagnosis when Event Viewer shows a generic "service failed to start" error — a situation that shows up often in logs investigated with Get-WinEvent.

Security Angle: Detecting Suspicious Services

Malware that installs persistence as a Windows service tends to follow recognisable patterns:

  • Names that resemble legitimate services (WindowsUpdate instead of wuauserv, for example)
  • An empty or overly generic DisplayName
  • An executable located outside System32 or Program Files

To check executable paths, combine this with Get-CimInstance:

Get-CimInstance Win32_Service |
  Select-Object Name, PathName, StartMode, State |
  Where-Object { $_.PathName -notlike "*System32*" -and $_.PathName -notlike "*Program Files*" }

This filters for services with executables in unusual locations — a red flag worth cross-checking against open-port monitoring with Get-NetTCPConnection to confirm whether the suspicious service is also opening active connections.

Get-Service looks simple, but combined with filters, exports and dependency checks it becomes a real auditing tool. If you're not yet automating the check for stopped automatic services after boot, this is the first script to add to your kit. To go further on this topic, the post on auditing logs with PowerShell covers the next level of visibility into a Windows environment.

Comments