Why “observe before action” matters
Processes and services are two common ways Windows runs work in the background. A process is a running program instance (for example, a browser tab group or a background agent). A service is a managed background component that Windows can start automatically and monitor (for example, Print Spooler). Many incidents happen because someone stops the wrong thing. The safe pattern is: (1) observe and identify the correct target, (2) confirm with names/IDs and key properties, (3) act with the least disruptive command, and (4) record what changed.
Inspecting processes with Get-Process
Core identifiers: Name vs Id
Get-Process returns process objects. Two properties are especially important:
- Name: friendly process name (often shared by multiple instances).
- Id: unique identifier for a specific running instance (safer when stopping a single target).
Start by listing and sorting to find candidates without acting:
# Top CPU consumers (snapshot at the moment you run it) Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 Name, Id, CPU, WorkingSet# Top memory consumers (WorkingSet is current RAM usage) Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 10 Name, Id, WorkingSet, PathTip: Some properties (like Path) may be blank for protected/system processes unless you run with elevated permissions.
Confirm the exact target before stopping
If a name appears multiple times, confirm which instance you mean by checking Id, StartTime, and (when available) Path:
Continue in our app.
You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.
Or continue reading below...Download the app
# Find all instances of a process name and confirm details Get-Process -Name notepad -ErrorAction SilentlyContinue | Select-Object Name, Id, StartTime, PathIf you only have an Id (for example, from Task Manager), verify it exists and matches what you expect:
$pid = 12345 Get-Process -Id $pid | Select-Object Name, Id, StartTime, PathActing on processes: Start-Process and Stop-Process
Starting a process safely
Start-Process launches an application. Prefer specifying a full path when possible to avoid starting the wrong executable from an unexpected location.
# Start Notepad Start-Process -FilePath notepad.exe # Start an app with arguments Start-Process -FilePath "C:\Program Files\7-Zip\7zFM.exe" -ArgumentList "C:\Temp"When you need to run elevated, use:
# Prompts for elevation (UAC) Start-Process -FilePath "cmd.exe" -Verb RunAsStopping a hung process (practical scenario)
A “hung” app might be unresponsive but still consuming CPU or memory. The goal is to stop the correct instance with minimal collateral damage.
Step-by-step: identify, confirm, stop
Observe symptoms (high CPU, high memory, or user reports). Find candidates:
Get-Process | Sort-Object CPU -Descending | Select-Object -First 15 Name, Id, CPU, RespondingFilter to the suspected app and confirm there aren’t multiple instances:
$name = "SomeApp" Get-Process -Name $name -ErrorAction SilentlyContinue | Select-Object Name, Id, Responding, StartTime, PathChoose the safest target (usually the specific
Idthat is not responding):$target = Get-Process -Name $name | Where-Object { $_.Responding -eq $false } | Select-Object -First 1 Name, Id, StartTime, PathStop by Id (more precise than name). Use
-WhatIffirst when you’re unsure:Stop-Process -Id $target.Id -WhatIfIf the preview looks correct, run the real stop:
Stop-Process -Id $target.IdEscalate only if needed. If the process refuses to exit, you may need
-Force(more disruptive):Stop-Process -Id $target.Id -Force
Safety notes:
- Avoid stopping system-critical processes (for example,
lsass,wininit,csrss). If you’re not sure what it is, stop and investigate first. - Stopping by
-Namecan terminate multiple instances. Prefer-Idfor a single target. - Permissions matter: stopping processes owned by other users or protected processes may require running PowerShell as Administrator.
Inspecting services with Get-Service
Service identifiers: Name vs DisplayName
Services have two common identifiers:
- Name: the service key name used by cmdlets (for example,
Spooler). - DisplayName: the friendly name shown in Services.msc (for example, “Print Spooler”).
When managing services, always confirm the Name you will act on:
# Search by display name text, then confirm the service Name Get-Service | Where-Object DisplayName -like "*print*" | Select-Object Name, DisplayName, StatusUnderstanding service Status and common pitfalls
Status is typically Running, Stopped, or transitional states. A service can also be disabled or require dependencies; those details are not fully visible in Get-Service output alone, so treat failures as a signal to inspect further (and expect that some actions require Administrator rights).
Generating a report of running services (practical scenario)
A service report is useful for audits, troubleshooting, or documenting a baseline before changes.
Step-by-step: build a clear, sortable report
Observe: list running services and sort by name for consistency:
$running = Get-Service | Where-Object Status -eq 'Running' | Sort-Object NameSelect the fields you want to report (keep it readable):
$report = $running | Select-Object Name, DisplayName, StatusOutput as a table for quick viewing:
$report | Format-Table -AutoSizeOptional: export for sharing (CSV is common for spreadsheets):
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss' $path = "C:\Temp\RunningServices-$timestamp.csv" $report | Export-Csv -Path $path -NoTypeInformation
Filtering and sorting guidance:
- Filter first (
Status -eq 'Running'), then sort (Sort-Object Name) to reduce noise and make output stable. - When searching by text, prefer narrowing by
DisplayNamebut act using the confirmedName.
Managing services: Start-Service, Stop-Service, Restart-Service
Permissions and safe previews
Starting/stopping services often requires running PowerShell as Administrator. If you get an “Access is denied” error, don’t keep retrying—re-run in an elevated session and confirm you’re targeting the right service.
Before changing anything, confirm current state:
$svcName = 'Spooler' Get-Service -Name $svcName | Select-Object Name, DisplayName, StatusStarting a stopped service
Start-Service -Name $svcName Get-Service -Name $svcName | Select-Object Name, StatusStopping a running service
Stopping a service can interrupt users. Confirm it’s the correct one and consider timing/impact.
Stop-Service -Name $svcName Get-Service -Name $svcName | Select-Object Name, StatusRestarting a service with clear logging (practical scenario)
When you restart a service for troubleshooting, you should record what changed: what the status was before, what action you took, and what the status became after. The following pattern creates a simple log entry you can keep for change tracking.
Step-by-step: restart with before/after status and timestamps
$svcName = 'Spooler' $logPath = 'C:\Temp\ServiceRestart.log' # Observe (before) $before = Get-Service -Name $svcName | Select-Object Name, DisplayName, Status # Act Restart-Service -Name $svcName # Observe (after) $after = Get-Service -Name $svcName | Select-Object Name, DisplayName, Status # Log what changed $entry = [PSCustomObject]@{ Time = Get-Date Service = $before.Name DisplayName= $before.DisplayName StatusBefore = $before.Status StatusAfter = $after.Status } $entry | Format-List | Out-String | Add-Content -Path $logPathNotes:
- If
StatusAfteris notRunning, treat it as a failure and investigate rather than repeatedly restarting. - For services that take time to settle, you may need to wait briefly and re-check status.
Avoiding the wrong target: practical filtering patterns
Processes: reduce ambiguity
- Prefer Id for actions: find by name, act by Id.
- Confirm path when possible: two different apps can share a similar name.
# Find candidates by partial name, then confirm and act by Id $candidates = Get-Process | Where-Object Name -like '*chrome*' | Select-Object Name, Id, Path $candidates | Sort-Object Name, IdServices: confirm the service Name you will use
Display names can be similar. Always confirm the exact Name field before calling Stop-Service or Restart-Service.
# Search by friendly name text, then confirm the service key name Get-Service | Where-Object DisplayName -like '*update*' | Sort-Object DisplayName | Select-Object Name, DisplayName, StatusUse “observe, then act” as a repeatable checklist
| Step | Processes | Services |
|---|---|---|
| Observe | Get-Process (CPU, WorkingSet, Responding) | Get-Service (Status, Name vs DisplayName) |
| Confirm | Prefer Id; check Path/StartTime | Confirm Name; check current Status |
| Act | Stop-Process (Id; -Force only if needed) / Start-Process | Start-Service, Stop-Service, Restart-Service |
| Verify | Re-run Get-Process to confirm it ended/started | Re-run Get-Service to confirm status changed |