Skip to main content

Debug a Script in Windows PowerShell

Problem

You want to diagnose failures or unexpected behavior in a script interactively.

Solution

To generate debugging statements from your script, Use the WriteDebug cmdlet. If you want to step through a region carefully, surround it with SetPsDebug –Step calls. To explore the environment at a specific point of execution, add a line that calls $host.EnterNestedPrompt().

Discussion

By default, PowerShell allows you to assign data to variables you haven’t yet created (thereby creating those variables). It also allows you to retrieve data from variables that don’t exist—which usually happens by accident and almost always causes bugs. To help save you from getting stung by this problem, PowerShell provides a strict mode that generates an error if you attempt to access a nonexisting variable. Example 132 demonstrates this mode.

Example 132. PowerShell operating in strict mode

PS >$testVariable = "Hello" PS >$tsetVariable += " World" PS >$testVariable Hello PS >RemoveItem Variable:\tsetvariable PS >SetPsDebug Strict PS >$testVariable = "Hello" PS >$tsetVariable += " World" The variable $tsetVariable cannot be retrieved because it has not been set

yet. At line:1 char:14

+ $tsetVariable <<<< += " World"

For the sake of your script debugging health and sanity, strict mode should be one of the first additions you make to your PowerShell profile.

When it comes to interactive debugging (as opposed to bug prevention), PowerShell supports several of the most useful debugging features that you might be accustomed to: tracing (through the SetPsDebug –Trace statement), stepping (through the SetPsDebug –Step statement), and environment inspection (through the $host. EnterNestedPrompt() call).

As a demonstration of these techniques, consider Example 133.

Example 133. A complex script that interacts with PowerShell’s debugging features

############################################################################## ## ## InvokeComplexScript.ps1 ## ## Demonstrates the functionality of PowerShell's debugging support. ## ##############################################################################

WriteHost "Calculating lots of complex information"

$runningTotal = 0 $runningTotal += [Math]::Pow(5 * 5 + 10, 2)

WriteDebug "Current value: $runningTotal"

SetPsDebug Trace 1 $dirCount = @(GetChildItem $env:WINDIR).Count

SetPsDebug Trace 2 $runningTotal = 10 $runningTotal /= 2

SetPsDebug Step $runningTotal *= 3 $runningTotal /= 2

$host.EnterNestedPrompt()

SetPsDebug off

As you try to determine why this script isn’t working as you expect, a debugging session might look like Example 134.

Example 134. Debugging a complex script

PS >$debugPreference = "Continue" PS >InvokeComplexScript.ps1 Calculating lots of complex information DEBUG: Current value: 1225

Example 134. Debugging a complex script (continued)

DEBUG: 17+ $dirCount = @(GetChildItem $env:WINDIR).Count DEBUG: 17+ $dirCount = @(GetChildItem $env:WINDIR).Count DEBUG: 19+ SetPsDebug Trace 2 DEBUG: 20+ $runningTotal = 10 DEBUG: ! SET $runningTotal = '1215'. DEBUG: 21+ $runningTotal /= 2 DEBUG: ! SET $runningTotal = '607.5'. DEBUG: 23+ SetPsDebug Step

Continue with this operation? 24+ $runningTotal *= 3

[Y]

Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y DEBUG: 24+ $runningTotal *= 3 DEBUG: ! SET $runningTotal = '1822.5'.

Continue with this operation? 25+ $runningTotal /= 2

[Y]

Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y DEBUG: 25+ $runningTotal /= 2 DEBUG: ! SET $runningTotal = '911.25'.

Continue with this operation? 27+ $host.EnterNestedPrompt()

[Y]

Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y DEBUG: 27+ $host.EnterNestedPrompt() DEBUG: ! CALL method 'System.Void EnterNestedPrompt()' PS >$dirCount

PS >$dirCount + $runningTotal 1207.25 PS >exit

Continue with this operation? 29+ SetPsDebug off

[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"):y DEBUG: 29+ SetPsDebug off

While not built into a graphical user interface, PowerShell’s interactive debugging features are bound to help you diagnose and resolve problems quickly.

For more information about the SetPsDebug cmdlet, type GetHelp SetPsDebug.

If you need dedicated infrastructure for debugging Windows PowerShell scripts, consider a Spain Dedicated Server for greater control over script execution, troubleshooting, system administration, automation, and Windows-based application workloads.

Help Category