Wednesday, March 26, 2008 10:18 PM bart

Windows PowerShell 2.0 Feature Focus - Script Debugging

Two weeks ago I did a little tour through Europe spreading the word on a couple of our technologies including Windows PowerShell 2.0. In this blog series I'll dive into a few features of Windows PowerShell 2.0. Keep in mind though it's still very early and things might change towards RTW - all samples presented in this series are based on the CTP which is available over here.

 

Introduction

Previously in this series we covered new scripting capabilities with script cmdlets, script internationalization and a few language enhancements in Windows PowerShell 2.0. But writing scripts is just one piece of the puzzle, how to debug those when something isn't quite right? To answer that question, Windows PowerShell 2.0 introduces script debugging capabilities.

 

Set-PsDebug

The Windows PowerShell debugging story embodies a series of features that cooperate with each other. First we have some configuration options using Set-PsDebug. This is the cmdlet you'll use to configure the debugging options of the system. There are a few configuration options:

  • -off: turns script debugging off
  • -trace: specifies a trace level, where 0 is like -off, 1 traces script execution on a line-per-line basis, 2 does the same but also traces variable assignment and function calls
  • -strict: like VB's Option Strict, makes the debugger throw an exception is a variable is used before being assigned to

Below is a run showing some Set-PsDebug options:

image

Notice all debugging output triggered by the trace level set through Set-PsDebug is prefixed with DEBUG. In order to write to the debug output yourself, there's Write-Debug which I'll leave as an exploration for the reader.

 

Working with breakpoints

Where it really gets interesting is the concept of breakpoints which are "points" where execution is "broken". In PowerShell that corresponds to the following:

  • A line (and column) number in a certain script;
  • Calls to a specified function;
  • Invocations of a specified command;
  • Variable access.

Once we have specified where we need to focus on what to do when the breakpoint is hit. When no action is specified, the shell will spawn a sub-shell that has access to the current state of the execution so that variables can be inspected and other actions can be taken during debugging. Alternatively, one can specify a script-block as an action.

Enough theory, let's map those concepts on cmdlets. Breakpoint in PowerShell are called PSBreakpoints, so let get-command be our guide:

image

It obviously all starts with New-PSBreakpoint and all other cmdlets are self-explanatory. Time to show a few uses of breakpoints. First, create a simple script called debug.ps1:

function bar {
   $a = 123
   if ($a -gt 100)
   {
      $a
      foo
   }
}

function foo {
   $a = 321
   Write-Host $a
}

"Welcome to PowerShell 2.0 Script Debugging!"
bar

Invoking it should produce no surprises:

image

First we'll set a breakpoint on a specific line of the script using New-PSBreakpoint -Script debug.ps1 -Line 16 and re-run the script. Notice - with tracing on to show line info of the script executing - we're breaking on the call to bar:

image

Also notice the two additional > signs to the prompt below. This indicates we've entered a nested debugging prompt. Now we need to control the debugger to indicate what we want to do. For that purpose there are a few Step-* cmdlets as shown below:

image

With Step-Into you simple go to the next statement, possibly entering a function call. With Step-Over you do the same, but you "step over" function calls straight to the line below the call. Step-Out is used to exit from a breakpoint and let the script continue to run till the next breakpoint is hit (or till it completes). A quick run:

image

So far we've been stepping through the code line-by-line. Notice the line numbers being shown next the DEBUG: word when tracing is enabled. The second DEBUG: line shows the output of the Step-Into command, showing where we'd end up next (preview of the next line). Now we're inside the foo function call, but you might wonder how we got there and which functions have been called before: enter Get-PsCallstack:

image

From the original prompt (0), we executed debug.ps1, which called into bar and foo subsequently to end up in the nested debugger prompt. While debugging you'll obviously want to investigate the system, for example to see what $a contains, so you can simple print the variable. Finally, we continue to step and exit the nested prompt because the script has stopped:

image

Time for some bookkeeping: let's get rid of this breakpoint. Easy once more, using Remove-PSBreakpoint:

image

So illustrate a few other concepts, we'll set a breakpoint on a function, on a command invocation and on variable access:

image

Re-run the script and watch out. Here's the output - we break four times: two variable $a assignments, one foo call and one call to Write-Host:

image

Notice the use of exit to escape from the nested prompt and to make the script execution continue to the next breakpoint. An alternative would be to use Step-Out. Especially the variable assignment debugger breakpoint option is very attractive because in lots of cases you see state of a variable being changed and you simple want to trace back where changes are happening.

Other stuff you might want to take a look into includes the -Action parameter to New-PSBreakpoint, the ability to clone breakpoints using -Clone, enabling/disabling breakpoints and the HitCount property of breakpoints.

For more information on debugging, simply take a look at get-help about_debug.

Happy debugging!

Del.icio.us | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:

Comments

# Windows PowerShell 2.0 Feature Focus - Script Debugging

Sunday, March 30, 2008 1:20 PM by DotNetKicks.com

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# Finds of the Week - March 30, 2008 » Chinh Do

Monday, March 31, 2008 10:01 PM by Finds of the Week - March 30, 2008 » Chinh Do

Pingback from  Finds of the Week - March 30, 2008 » Chinh Do