PowerShell How-To

Understanding Debugging Breakpoints in PowerShell

Breakpoints will help in narrowing down where your code has failed.

Code doesn't always go as planned. It would be great if we all could write code that works perfectly all the time but ultimately bugs will creep in and our code never works right the first time. Debugging is here to help. Debugging is a necessary evil in the software development work and as such is necessary with PowerShell code development. One of the primary requirements of debugging is code control. To properly debug a script it must be controlled which means not just executing the entire script at once. We need control to step through the components to analyze results. Breakpoints are one way to gain control.

Breakpoints are a great way to tell your code to stop at certain points. In PowerShell, breakpoints can be triggered a few different ways. They can be triggered when a certain command is run, when a variable is touched or when a specific line in a script is run. When a breakpoint is hit, PowerShell drops into a different state known as the debugger. The debugger is separate console where different commands can be passed to track down the state that your code is in at the time. Breakpoints give you ultimate control of what to do when your code is being executed.

The easiest way to understand breakpoints and the debugger is by using a few PowerShell commands for managing breakpoints. In this article, we'll be focusing on Get-PSBreakpoing and Set-PSBreakpoint but a full list can be found by running Get-Command -Name *Breakpoint*.

Let's start with an example piece of code that incoporates each of the breakpoint triggers available to us.

$foo = 'bar'

if ($foo -eq 'bar') {

$baz = 'fooisbar'

$var = Get-ChildItem -Path C:\test123

} else {

$baz = 'fooisnotbar'

$var = Get-ChildItem -Path C:\test1234

}

Write-Host 'Script is done'

When this script is run, the variable var will include the folder contents of either C:\test123 or C:\test1234 depending on the variable value of $foo is. Also, the variable $baz will change as well. As-is, this script does not return anything so without some debugging, we have no way to truly know the value of either $baz or $var ever is. Let's set a breakpoint to perform some investigation.

To set breakpoints, we'll use the Set-PSBreakpoint command. Let's first use this command and set the line trigger to stop code execution and drop down into the debugger at line 3.

PS> Set-PSBreakpoint -Line 9 -Script C:\Users\Adam\test.ps1



ID Script Line Command Variable Action

-- ------ ---- ------- -------- ------

5 test.ps1 9

I'll now run this script and notice what happens.

PS> C:\Users\Adam\test.ps1

Entering debug mode. Use h or ? for help.



Hit Line breakpoint on 'C:\Users\Adam\test.ps1:3'



At C:\Users\Adam\test.ps1:3 char:5

+ $baz = 'fooisbar'

+ ~~~~~~~~~~~~~~~~~

PS> h



s, stepInto Single step (step into functions, scripts, etc.)

v, stepOver Step to next statement (step over functions, scripts, etc.)

o, stepOut Step out of the current function, script, etc.



c, continue Continue operation

q, quit Stop operation and exit the debugger

d, detach Continue operation and detach the debugger.



k, Get-PSCallStack Display call stack



l, list List source code for the current script.

Use "list" to start from the current line, "list <m>"

to start from line <m>, and "list <m> <n>" to list <n>

lines starting from line <m>



<enter> Repeat last command if it was stepInto, stepOver or list



?, h displays this help message.





For instructions about how to customize your debugger prompt, type "help about_prompt".

At this point we can do a number of different things but I just want to see what the value of various variables are at the time. To do that, I simply look at the variable values in the debugger and it will show me the value at the time of line 9.

PS> C:\Users\Adam\test.ps1

Hit Line breakpoint on 'C:\Users\Adam\test.ps1:9'



At C:\Users\Adam\test.ps1:9 char:1

+ Write-Host 'Script is done'

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~

PS> $foo

bar

PS> $var





Directory: C:\test123





Mode LastWriteTime Length Name

---- ------------- ------ ----

-a---- 4/22/2017 9:15 AM 2 test123.txt

I can do the same thing using a variable as well. Perhaps I need to find out what $var is when Write-Host is invoked. I can do this by starting the debugger when Write-Host is invoked by using the Variable parameter on Set-PSBreakpoint.

PS> Set-PSBreakpoint -Command 'Write-Host' -Script C:\Users\Adam\test.ps1



PS> C:\Users\Adam\test.ps1

Hit Command breakpoint on 'C:\Users\Adam\test.ps1:Write-Host'



At C:\Users\Adam\test.ps1:9 char:1

+ Write-Host 'Script is done'

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~

[FUSIONVM] - C:\> $var





Directory: C:\test123





Mode LastWriteTime Length Name

---- ------------- ------ ----

-a---- 4/22/2017 9:15 AM 2 test123.txt

When we're done we can remove the breakpoints by using Remove-PSBreakpoint.

Get-PSBreakpoint | Remove-PSBreakpoint

Breakpoints are a powerful debugging feature in PowerShell. They give you complete control and allow you to "slow down" code execution to allow us humans to peer into what our code is actually doing as it's doing it. For a full breakdown of what you can do with breakpoints, check out the PowerShell help for each of the commands. The help content contains a ton of great examples.