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
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.

About the Author

Adam Bertram is a 20-year veteran of IT. He's an automation engineer, blogger, consultant, freelance writer, Pluralsight course author and content marketing advisor to multiple technology companies. Adam also founded the popular TechSnips e-learning platform. He mainly focuses on DevOps, system management and automation technologies, as well as various cloud platforms mostly in the Microsoft space. He is a Microsoft Cloud and Datacenter Management MVP who absorbs knowledge from the IT field and explains it in an easy-to-understand fashion. Catch up on Adam's articles at adamtheautomator.com, connect on LinkedIn or follow him on Twitter at @adbertram or the TechSnips Twitter account @techsnips_io.

comments powered by Disqus
Most   Popular