The term "debug" can mean a lot of things, but in the PowerShell sense, I'm referring to "debugging" as using the PowerShell debugger.

Some consider debugging a black art. It's an activity shrouded in mystery until you actually sit down to learn! Especially with IT pros, we think of debugging code as something only developers do. But as PowerShell becomes more popular amongst IT pros, and we automate more complex tasks with it, there are times when simply inserting Write-Host references throughout your script isn't enough. You need more control, and you can gain that control through the PowerShell debugger.

The PowerShell debugger is a debugging system built right into the engine that allows you to stop code execution mid-stream and investigate the code at a certain spot. We've all probably run into a problem where a variable is set to some unknown value. But by the time the script completes, it's gone, and we can never figure out what value it held at a specific time. With the PowerShell debugger, we can stop the script at that exact point and investigate what the variable's value is, check out the call stack, and more.

Unlike other languages, debugging support is available within PowerShell itself. There's no need to use any external tool to do this. The more important part of understanding PowerShell debugging is understanding the breakpoint. The breakpoint is a place inside of the code where PowerShell "breaks" into the debugger. The code doesn't actually separate into two pieces but rather just stops, and depending on how it's configured, it either waits for your input or performs some other kind of action.

Breakpoints have a "trigger." Triggers or types of breakpoints are events that tell PowerShell when to stop code execution. In PowerShell, we have three types of breakpoints:

  • Line
  • Command
  • Variable

The type of event that happens inside the code indicates when it triggers a breakpoint. For example, if a line breakpoint is set, the code pauses execution on a particular line of a script or module. If a command breakpoint is set, the code pauses execution upon invoking a function, cmdlet, or some other expression. Creating, updating, or accessing a variable with a certain name triggers a variable breakpoint. With these three types of breakpoints, you can pause code execution anywhere within the code.

To set a breakpoint, we use the Set-PSBreakPoint cmdlet. The Set-PSBreakPoint cmdlet has a few common parameters we can use depending on the type of breakpoint required. For example, perhaps we have a script that contains some typical conditional logic and a few variables. The function below starts a Windows service based on the value of Name.

function Install-Application {
    param(
        $ComputerName,
        $Name
    )

    if ($Name -eq 'service1') {
        $windowsServiceName = 'foo'
    } else {
        $windowsServiceName = 'bar'
    }
    Start-Service -Name $windowsServiceName -ComputerName $ComputerName
}

Perhaps when this runs, it starts the wrong service. Since the $windowsServiceName variable is only being set inside of the function, we can't directly control that. Its value depends on the value of Name. I'd like to ensure Start-Service is receiving the right value of Name. To do this, I can set a breakpoint on the Start-Service command to force the code to pause right before executing Start-Service; I do this with Set-PSBreakpoint -Variable windowsServiceName.

Normally, when I'd execute this function, it would happily run all the way through and attempt to start the appropriate service. However, this time, it stops:

PS C:\> install-application -Name 'thing'
Hit Variable breakpoint on '$windowsServiceName' (Write access)

At line:10 char:9
+         $windowsServiceName = 'bar'
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DBG]: PS C:\>>

Execution stops at line 10, character 9, which is the line $windowsServiceName = 'bar'. You can also see the prompt is a little different from the [DBG] indicator. This means we're in debug mode. At this point, I can see what value $windowsServiceName is.

[DBG]: PS C:\>> $windowsServiceName
bar

Since we're still in the console, I can actually do just about anything else. I could run Get-Service to check on the service status, ping the server, or do whatever else I need to. Our function is paused at a point in time. By typing "?" we can also display the available options.

Available debug commands

Available debug commands

When we're done investigating, we can just hit c to continue, and the function will complete as it originally would.

Subscribe to 4sysops newsletter!

We were only able to get into the basics of debugging in this article, but if you're working with complex code, you've got a lot of other options you can use. The Scripting Guy blog has a great article that goes a little more in-depth, especially on the debug console commands you have available after triggering the breakpoint.

+4
avatar
0 Comments

Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *

*

© 4sysops 2006 - 2021

CONTACT US

Please ask IT administration questions in the forums. Any other messages are welcome.

Sending

Log in with your credentials

or    

Forgot your details?

Create Account