Debugging
Prerequisites: Advanced functions
Look at the data
Most PowerShell bugs come from data not being what you think. Check types, counts, and properties:
$result = 'web01'
$result.GetType().Name
@($result).Count
[pscustomobject]@{ Name = 'web01'; Port = 443 } | Format-List *
String
1
Name : web01
Port : 443
Format-List * shows every property; Get-Member shows the type and
members.
Strict mode
Set-StrictMode turns silent mistakes into errors:
Set-StrictMode -Version Latest
$user = [pscustomobject]@{ Name = 'Ada' }
try { $user.Nmae } catch { $_.Exception.Message }
try { $undefinedVariable } catch { $_.Exception.Message }
The property 'Nmae' cannot be found on this object. Verify that the property exists.
The variable '$undefinedVariable' cannot be retrieved because it has not been set.
Without strict mode, both lines would silently return $null. Put
Set-StrictMode -Version Latest at the top of scripts.
Verbose and debug output
Sprinkle Write-Verbose through advanced functions and run them with
-Verbose to trace what happens — the messages stay out of the data and
are invisible otherwise.
Breakpoints
In VS Code, click left of a line number to set a breakpoint and press F5. Execution pauses there; you can inspect variables, step through lines (F10), step into functions (F11), and type expressions in the debug console.
From the console, set breakpoints with Set-PSBreakpoint:
# illustrative
Set-PSBreakpoint -Script .\deploy.ps1 -Line 42
Set-PSBreakpoint -Script .\deploy.ps1 -Variable total -Mode Write
.\deploy.ps1
At the [DBG] prompt, type s (step into), v (step over), o (step
out), c (continue), k (call stack), or any expression. Adding
Wait-Debugger to a script pauses it at that line.
Tracing commands
Set-PSDebug -Trace 1 prints each line as it runs — like set -x in Bash.
Turn it off with Set-PSDebug -Off.
What's next
Try the Intermediate Projects, then move on to Level 3 — Advanced: classes, .NET, parallelism, remoting, and building production-ready modules.