Weekend Scripter: Break in to a Script via a Command


Summary: Ed Wilson, Microsoft Scripting Guy, talks about using the debugger to break in to a script via a specific command.

Microsoft Scripting Guy, Ed Wilson, is here. One of the cool things, when troubleshooting a specific function in Windows PowerShell, is to set a breakpoint to occur each time the command is called. Remember, Windows PowerShell functions are also Windows PowerShell commands, just as language statements and cmdlets are.

To set the breakpoint in a command, you use the -command parameter. You can break on a call to a Windows PowerShell cmdlet, function, or external script. You can use aliases when setting breakpoints. When you create a breakpoint on an alias for a cmdlet, the debugger will only stop on the use of the alias—not on the actual command name.

In addition, you do not have to specify a script for the debugger to break. If you do not type a path to a script, the debugger will be active for everything within the Windows PowerShell console session. Every occurrence of the Foreach command will cause the debugger to break. The command to set such a breakpoint is shown here:

Set-PSBreakpoint -Command Foreach

Because Foreach is a language statement in addition to an alias for the Foreach-Object cmdlet, you might wonder whether the Windows PowerShell debugger will break on the language statement and on the use of the alias for the cmdlet. The answer is no.

You can set breakpoints on language statements, but the debugger will not break on a language statement. As shown here, the debugger breaks on the use of the Foreach alias, but not on the use of the Foreach-Object cmdlet or the % alias:

PS C:\> 1..3 | Foreach-Object {$_}
1
2
3
PS C:\> 1..3 | % {$_}
1
2
3
PS C:\> 1..3 | foreach {$_}
Hit Command breakpoint on 'foreach'

At line:1 char:1
+ 1..3 | foreach {$_}
+ ~~~~~~~~~~~~~~~~~~~
[DBG]: PS C:\>> c
1
2
3
PS C:\>

Note You can use the shortcut technique of creating the breakpoint for the Windows PowerShell session and not specifically for the script. By leaving out the -script parameter when creating a breakpoint, you cause the debugger to break in to any running script that uses the named function. This allows you to use the same breakpoints when debugging scripts that use the same function.

When creating a breakpoint for the DivideNum function that is used in the C:\FSO\BadScript.ps1 script, you can leave off the path to the script, because only this script uses the DivideNum function.

This makes the command easier to type, but it could become confusing if you’re looking through a collection of breakpoints. If you are debugging multiple scripts in a single Windows PowerShell console session, it could become confusing if you do not specify the script to which the breakpoint applies—unless, of course, you are specifically debugging the function as it is used in multiple scripts.

Creating a command breakpoint for the DivideNum function is shown here:

PS C:\> Set-PSBreakpoint -Command DivideNum

  ID Script            Line Command           Variable         Action
  -- ------            ----       -------                --------            ------
   7                        DivideNum

When you run the script, it hits a breakpoint when the DivideNum function is called. When BadScript.ps1 hits the DivideNum function, the value of $num is 0. As you step through the DivideNum function, you assign a value of 2 to the $num variable, a result of 6 is displayed, and then the 12/$num operation is carried out.

Next, the AddOne function is called and the value of $num once again becomes 0. When the AddTwo function is called, the value of $num also becomes 0. This is shown here:

PS C:\> C:\fso\BadScript.ps1
Hit Command breakpoint on 'DivideNum'

At C:\fso\BadScript.ps1:37 char:1
+ {
+ ~
[DBG]: PS C:\>> s
At C:\fso\BadScript.ps1:38 char:2
+  12/$num
+  ~~~~~~~
[DBG]: PS C:\>> $num
0
[DBG]: PS C:\>> $num=2
[DBG]: PS C:\>> s
6
At C:\fso\BadScript.ps1:39 char:1
+ } #end function DivideNum
+ ~
[DBG]: PS C:\>> s
At C:\fso\BadScript.ps1:45 char:1
+ AddOne($num) | AddTwo($num)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
[DBG]: PS C:\>> $num
0
[DBG]: PS C:\>> s
At C:\fso\BadScript.ps1:12 char:1
+ {
+ ~
[DBG]: PS C:\>> q
PS C:\>

Responding to breakpoints

When the script reaches a breakpoint, control of the Windows PowerShell console is turned over to you. Inside the debugger, you can type any legal Windows PowerShell command, and even run cmdlets such as Get-Process or Get-Service.

In addition, there are several new debugging commands that can be typed into the Windows PowerShell console when a breakpoint has been reached. The available debug commands are shown in the following table.

Windows PowerShell debugging commands

Keyboard shortcut

Command name

Command meaning

S

Step-Into

Executes the next statement and then stops.

V

Step-Over

Executes the next statement, but skips functions and invocations. The skipped statements are executed, but not stepped through.

O

Step-Out

Steps up one level in the current function, if nested. If in the main body, it continues to the end or the next breakpoint. The skipped statements are executed, but not stepped through.

C

Continue

Continues to run until the script is complete or until the next breakpoint is reached. The skipped statements are executed, but not stepped through.

L

List

Displays the part of the script that is executing. By default, it displays the current line, 5 previous lines, and 10 subsequent lines. To continue listing the script, press ENTER.

L <M>

List

Displays 16 lines of the script, beginning with the line number specified by M.

L <M> <N>

List

Displays the number of lines of the script specified by N, beginning with the line number specified by M.

Q

Stop (Quit)

Stops executing the script and exits the debugger.

K

Get-PsCallStack

Displays the current call stack.

ENTER

Repeat

Repeats the last command if it was Step-Into, Step-Over, or List. Otherwise, represents a submit action.

H or ?

Help

Displays the debugger command Help.

That wraps up Debugging Week. I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (0)

Skip to main content