Is there a way to enter the PowerShell debugger in response to an error? The ErrorAction
parameter has several values but I don't see anything like Debug
. What I would like is to open the debugger like it would open if I had set a breakpoint, but only when an error occurs (from, say, Write-Error
).
Edit I should clarify a bit: I am primarily a C# developer and somewhat new to PowerShell, what I am expecting is behavior similar to what the Visual Studio debugger gives you for "unhandled exceptions". It appears that it is more common for PowerShell commands to throw exceptions, while custom scripts seem to mostly use Write-Error. I don't think I particularly care to distinguish between the two, but I would like to handle both.
Trevor Sullivan's answer below mentions that you can use Set-PSBreakpoint -Command Write-Error -Action { break; };
which appears to work well to catch those cases. Though, I am finding that in many cases it is actually a command throwing an exception that I would like to break on. Roman Kuzmin's answer appears to work if you set $ErrorActionPreference = "stop"
, however, I have the problem that I cannot step through the program, it seems to break out of that location and end the script. If $ErrorActionPreference = "continue"
it does not work for me. Traps in general seem to have a similar issue that they break out out of any nested scopes, which is not desired.
You could create a function that sets a breakpoint on a variable, then changes the value of the variable.
Then call the function from a trap a the top of the script to catch all terminating errors.
Or call it from a
try-catch
statement.Once you are in debug mode, check
$Error[0]
to see what triggered the breakpoint.Yes, there is a simple way to break into the debugger on errors. It looks like each time when an error happens the variable
StackTrace
gets updated. So I use this trick: in my profile I have these two functions (switches):When the first is called then breaking into the debugger on errors is actually enabled. On errors
StackTrace
is written and this triggers the breakpoint.The second function turns breaking into the debugger on errors off.
In most cases this approach works for me just fine.
UPDATE
In order to use this technique without profile functions a helper script like Debug-Error.ps1 can be used. Ideally, it should should be located in the path, so that commands
Debug-Error
andDebug-Error -Off
are always available.See also this blog post.
A few related tickets on Connect:
Of course. You can create conditional breakpoints in PowerShell, using the
Set-PSBreakpoint
cmdlet. Consider the following code. Save it as a script file, and execute it. There are in-line comments to help you understand what's going on.Keep in mind that there are three different types of breakpoints:
Command Breakpoint
This code example is using the command breakpoint type, because I am telling it to only set breakpoints on
Get-WmiObject
commands. You can alternately specify a specific line number or a variable breakpoint type. You use the-Action
parameter to specify the conditions under which you want the breakpoint to be set. You must use thebreak
keyword somewhere inside the-Action
ScriptBlock
in order to instruct the debugger to pause execution of the PowerShell script.Since you mentioned using
Write-Error
, you could set aPSBreakpoint
on lines whereWrite-Error
appears. Here is an example of how to do that:Pretty easy, right?
Variable Breakpoint
This example uses the variable
PSBreakpoint
type, but only when the variable's contents are modified. You can use the-Mode
parameter to determine under what conditions the variable breakpoint is hit:Code:
Line Breakpoint
Now that we've looked at the variable and command
PSBreakpoint
types, the last type of breakpoint to explore is the line breakpoint. If you were to copy/paste the code below, save it, and execute it, you would see that the code breaks on the Write-Host line (which happens to be line 9), but only when theName
property of the$Service
variable is equal toWinRM
. That is what the conditional statement in the-Action
parameter'sScriptBlock
defines.Kinda hokey but works on write-error or throw statements: