Debugging Monad Scripts, Part 6: Trace-Expression, Breakpoint Script

Did your command or script fail and/or report an error?  We hope to have a proper script debugger in a future version, but until then, MSH has some handy features to help you figure out what went wrong.  In this series of blog entries, I will present some of those features.  Thanks to Jim Truher [MSFT], Bruce Payette [MSFT], and Jeff Jones [MSFT] for their help in putting this together.

See the Windows "Monad" Shell Beta 2 Documentation Pack (https://www.microsoft.com/downloads/details.aspx?FamilyID=8a3c71d1-18e5-49d7-952a-c55d694ecee3&displaylang=en) for general information about Monad.

Part 1: https://blogs.msdn.com/monad/archive/2005/11/04/489138.aspx (Terminating vs. Non-Terminating Errors, ErrorRecord)
Part 2: https://blogs.msdn.com/monad/archive/2005/11/08/490130.aspx ($error)
Part 3: https://blogs.msdn.com/monad/archive/2005/11/09/490625.aspx (write-host)
Part 4: https://blogs.msdn.com/monad/archive/2005/11/09/491035.aspx (set-mshdebug)
Part 5: https://blogs.msdn.com/monad/archive/2005/11/11/491967.aspx (Preferences and Commandline Options)

Jon Newman [MSFT]

 


Trace-Expression: Using Tracing

Monad contains built-in tracing which you can enable using the trace-expression cmdlet. We use this for detailed debugging of our own code, and when bugs come in from our customers, we often ask that they turn on specific tracing categories and send us the expanded output. You can also use this to understand what is happening in your own scenarios, although you should expect that the tracing output will be highly technical, and will not be translated to other languages. The Windows "Monad" Shell Beta 2 Documentation Pack (https://www.microsoft.com/downloads/details.aspx?FamilyID=8a3c71d1-18e5-49d7-952a-c55d694ecee3&displaylang=en) already contains excellent information in "TracingQuickStart.doc", so I won't elaborate on it here.

 


Breakpoint Script

Jeff Jones [MSFT] proposes the following scriptlet for creating breakpoints in Monad scripts:

function start-debug
{
$scriptName = $MyInvocation.ScriptName
function prompt
{
"Debugging [{0}]>" -f $(if ([String]::IsNullOrEmpty($scriptName)) { "globalscope" } else { $scriptName } )
}
$host.EnterNestedPrompt()
}
set-alias bp start-debug

You can dot-source these in your profile or add them directly to your script, then set a breakpoint by inserting "bp" in the script. When this line is hit it puts you into a nested prompt with a modified prompt that tells you what you are debugging. You can examine variables, functions, etc, and when you are done you type "exit" and the script starts running again. This is great when you have a long script and you don't want to step through the whole thing using set-mshdebug -Step.

Comments

  • Anonymous
    November 17, 2005
    I really like the breakpoint script. I've tweaked it some to add the ability to disable the breakpoint:

    <pre>
    $global:__breakpointsEnabled=$true

    set-alias bp start-debug
    function start-debug
    {
    if (-not $global:__breakpointsEnabled) { return }

    $scriptName = $MyInvocation.ScriptName
    $lineNumber = $MyInvocation.ScriptLineNumber
    function prompt
    {
    "Bkpt: {0}:{1} ! " -f
    $(if ([String]::IsNullOrEmpty($scriptName)) {
    "globalscope","?"
    }
    else {
    (parse-path $scriptName -Leaf), $lineNumber
    })
    }
    $host.EnterNestedPrompt()
    }

    set-alias ebp enable-breakpoints
    function enable-breakpoints {
    $global:__breakpointsEnabled = $true
    "Breakpoints enabled"
    }

    set-alias dbp disable-breakpoints
    function disable-breakpoints {
    $global:__breakpointsEnabled = $false
    "Breakpoints disabled"
    }
    </pre>
  • Anonymous
    November 18, 2005
    Here's a way to skip breakpoints:

    $global:__breakpointSkipCount = 0

    set-alias bp start-debug
    function start-debug
    {
    if (-not $global:__breakpointsEnabled) { return }
    if ($global:__breakpointSkipCount -gt 0) {
    $global:__breakpointSkipCount--
    return
    }

    $scriptName = $MyInvocation.ScriptName
    $lineNumber = $MyInvocation.ScriptLineNumber
    function prompt
    {
    "Bkpt: {0}:{1} ! " -f
    $(if ([String]::IsNullOrEmpty($scriptName)) {
    "globalscope", "?"
    }
    else {
    (parse-path $scriptName -Leaf), $lineNumber
    })
    }
    set-mshdebug -step
    }

    set-alias sbp skip-breakpoints
    function skip-breakpoints([int]$num) {
    $global:__breakpointSkipCount = $num
    }
  • Anonymous
    April 25, 2006

    Did your command or script fail and/or report an error?&amp;nbsp; We hope to have a proper script debugger...
  • Anonymous
    June 24, 2007
    So why do you care about debugging powershell scripts? Umm unless you have the superhuman ability to