PowerShell challenge lab: build a complete report
Documentation: Microsoft Learn
The challenge lab brings several decisions into one report: what to collect, which objects to keep and how to present the result. Use daily practice to rehearse an individual stage before attempting the whole task.
Choose your next task: short checked exercises · type and inspect a pipeline · assemble command blocks · a short daily task · choose a reporting workflow · read an individual script ·
1. Download and inspect the lab
Download the complete lab ZIPIncludes servers.txt, services.json, starter.ps1, solution.ps1 and a README. Compatible syntax targets Windows PowerShell 5.1 and PowerShell 7; the reference has not been executed against live infrastructure.
Read the server list. SRV01 and SRV02 have service records; SRV03 is unreachable. Open starter.ps1 and build the pipeline yourself before reading the reference solution.
2. Meet the acceptance criteria
- Read input files relative to the script folder.
- Keep only services whose StartType is Automatic and Status is Stopped.
- Return ComputerName, Name, DisplayName, StartType, Status and Error.
- Retain SRV03 as one error row; its service fields must be blank.
- Export objects once with Export-Csv and -NoTypeInformation.
The original fixture produces exactly three records: Spooler on SRV01, WinRM on SRV02, and an error for SRV03. A server without matching services contributes no service row.
3. Ask for the smallest hint
Hint 1 — read the data
Use Get-Content -Raw | ConvertFrom-Json for the fixture, and Get-Content for servers.txt. Join-Path and $PSScriptRoot avoid relying on your current directory.
Hint 2 — filter without hiding failures
Use per-server try/catch. Check Reachable before inspecting Services. The service filter needs both comparisons joined with -and.
Hint 3 — keep one output shape
Use [pscustomobject] for both successful rows and error rows. Keep the same six properties in each object; collect them before exporting.
4. Check your CSV locally in this page
The checker reads CSV only. It does not execute or certify your script. Nothing you paste is sent to the server.
5. Compare the implementation
Reveal the reference solution
# Fictional-data solution: no network access and no service changes.
# Run from this extracted folder: .\solution.ps1
[CmdletBinding()]
param([string]$InputFolder = $PSScriptRoot,
[string]$OutputPath = (Join-Path $PSScriptRoot 'service-audit.csv'))
$servers = Get-Content (Join-Path $InputFolder 'servers.txt') -ErrorAction Stop |
ForEach-Object { $_.Trim() } | Where-Object { $_ } | Select-Object -Unique
$fixture = Get-Content (Join-Path $InputFolder 'services.json') -Raw -ErrorAction Stop | ConvertFrom-Json
$results = foreach ($computer in $servers) {
try {
$record = @($fixture | Where-Object ComputerName -eq $computer)
if ($record.Count -ne 1) { throw "Expected one fixture for $computer" }
if (-not $record[0].Reachable) { throw 'Unreachable' }
foreach ($service in $record[0].Services) {
if ($service.StartType -eq 'Automatic' -and $service.Status -eq 'Stopped') {
[pscustomobject][ordered]@{
ComputerName = $computer
Name = $service.Name
DisplayName = $service.DisplayName
StartType = $service.StartType
Status = $service.Status
Error = ''
}
}
}
} catch {
[pscustomobject][ordered]@{
ComputerName = $computer; Name = ''; DisplayName = ''
StartType = ''; Status = ''; Error = $_.Exception.Message
}
}
}
$results | Export-Csv -LiteralPath $OutputPath -NoTypeInformation -Encoding UTF8
$results
The try/catch belongs inside the loop so one unreachable server does not discard other results. The error object preserves the target name. Export-Csv receives objects rather than display text.
6. Test a variation
Change the fixture: make every service Running, add a second unreachable server, then add a stopped Manual service. Predict each result before running your script. The browser checker accepts the original fixture only; use your own expected records for these variations.
For real Windows servers, Get-CimInstance Win32_Service uses StartMode (Auto) and State (Stopped), rather than this fixture’s StartType (Automatic) and Status. Map the properties explicitly, use per-target error handling, and verify access and remoting before adapting the report.
Microsoft: Win32_Service propertiesPractice archive and next project
This is the first expanded challenge lab. Future published labs will be listed here; the site does not pretend to release new content automatically.