You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Change in behaviour of -Debug common parameter #10873
In PowerShell up to 5.1 -Debug set the debug preference to Inquire which allowed the code being run to drop into a nested prompt.
In 6 and 7 it sets it to continue which makes write-debug similar to write-verbose . Inquire has to be set via$debugActionPreference
Further: "Inquire" offers a suspend option (drop to nested prompt) which can't be set via $debugActionPreference and $debugActionPreference offers break (drop to debugger) which can't be selected via the inquire prompt
Are these by design ? If so what's the logic of -debug printing messages but not providing access to debugging ?
Kirk Munro (@KirkMunro) can probably explain it much better than I'm able to, since he wrote all that fun code. 😊
The short version (probably missing a good deal of context myself, but what I know atm) is: -Debug was generally very unusable for the way most folks were wanting to use it, and completely unusable in CI environments, where ostensibly a lot of folks could stand to use it more.
Things like -ErrorAction Break or $debugActionPreference = 'Break' were added to actually drop into the debugger on error or debug when you wanted to, but most folks were generally finding -Debug fairly unusable with the constant prompting.
ActionPreference.Suspend was for workflows and workflows only. We don't have workflows anymore, ergo, no ActionPreference.Suspend support. We're still keeping the enumeration around, but it's reserved for future use at this time. I'm just calling that out since we're talking a little about Suspend as well as ActionPreference here.
The Suspend option in the handling of ActionPreference.Inquire is different than ActionPreference.Suspend. In the context of the Inquire prompt, Suspend drops you into a nested prompt. Nested prompts offered a way to do some inspection in PowerShell in v1, before PowerShell had a debugger. When it comes to debugging, today they offer much less value than the built-in debugger support. See also ActionPreference.Inquire is inconsistent and needs some redesign #9755.
ActionPreference.Debug was always about outputting debug messages. In PowerShell v1, when we didn't have a debugger, it also provided a way to get into a nested prompt so that you could look around and troubleshoot some things. It was not an actual debugger though -- you would be in a nested prompt (different scope), and you couldn't step through code, look at the code you were debugging using a debugger command, etc.
Given the very limited usefulness of entering a nested prompt vs actually debugging, we added ActionPreference.Break for those times when you want to break into a debugger and troubleshoot. This is what you should use if you want to enter the debugger and troubleshoot something.
Further, since Write-Debug would result in interactive prompting, users who wanted to output messages in PowerShell that were not shown by default would always use Write-Verbose, but that's not a great model, and has resulted in too much messaging being pumped through the Verbose stream. Verbose messages are for extra messages that should help an end user figure out what is going wrong when something isn't working. Debug messages are for extra messages that should help a developer figure out exactly what is happening when something is going wrong with a script or command they authored that is being run on another system.
To sum up:
Feature
PowerShell 5.1
PowerShell 7+
-Debug
Output debug messages in an interactive prompt that would allow you to enter a nested prompt (but not actually a debugger) to troubleshoot.
Output debug messages so that we can have two levels of extra output when necessary (one for Verbose and one for Debug)
ActionPreference.Break
N/A
Break into the debugger when a specific type of message is generated, the moment that message is generated (e.g. -ErrorAction Break)
In both cases, ActionPreference.Inquire still exists, but is of questionable usefulness (again, see the discussion on #9755).
Other items related to this discussion that you may want to be aware of:
Support ScriptBlocks in -*Action common parameters and *Preference variables to process errors and messages PowerShell-RFC#219 - this RFC proposes adding ScriptBlock support to -*Action common parameters, and $*Action preference variables, so that what they do can be decided on at runtime based on the actual *Record or Exception that caused the ScriptBlock to be invoked. That will allow people to break into the debugger when a certain type of message is generated, but only if it has specific properties (e.g. certain exception type, or error ID, or debug message string).
Thanks all (esp Kirk Munro (@KirkMunro)) for the detail. I was checking something I'd written a while back and found the behaviour had changed. I rarely use write-debug for exactly the reasons given as a rationale for the change :-) so I hadn't spotted it before.
Initially I didn't think -debug as "super verbose" was a good idea, but having read the links above (Kirk again) it makes more sense than the other options. Inquire is of limited use, especially as it doesn't offer to drop into debug, only the nested prompt, and the number of times we need <<message>> Stop or Continue ? messages as part of debugging is small.
The more I think about it the more its seems any problem here is that this change is so long overdue. I'm assuming other have grown used to something has worked, but quite poorly, so when it is made to work better, the change jars. Now I've read the docs, I think that's OK.
3 observations
The error message when setting the preference to "suspend" in 6 and later could be better.
The message printed by write-debug only appears when execution returns from the debugger, it should really appear first. .
The debugger doesn't have the equivalent of "yes to all" in inquire, but as a work-round setting $debugpreference in the debugger sets it for the local scope, which is OK.
But since the question is answered, and there is no bug so I'm going to close this issue.
The error message when setting the preference to "suspend" in 6 and later could be better.
The current message is "The Suspend ActionPreference value is reserved for future use and is not supported at this time. For more information about preference variables, see the Help topic, "about_Preference_Variables."" What do you think is missing from that message?
The message printed by write-debug only appears when execution returns from the debugger, it should really appear first. .
This is by design.
PowerShell breaks into the debugger the moment the message is created so that you can look around at that point. Having it break into the debugger once the message is written to the host means unwinding the stack more and so you may lose some visibility on what was going on.
That said, in addition to showing the breakpoint line, we could consider showing the message text or some details about the trigger object (which is just an ErrorRecord, Exception, DebugRecord, etc.) when we enter the debugger based on a message, so that users see the stream message that triggered the breakpoint.
The debugger doesn't have the equivalent of "yes to all" in inquire, but as a work-round setting $debugpreference in the debugger sets it for the local scope, which is OK.
You're right. There are more things that could be done here, such as:
continue without breaking on other Error/Debug/etc. messages
making the detach (d) debugger command work for local script debugging as a way to tell PowerShell to disable the debugger until the current execution completes, running the command to completion without other breakpoints being triggered.
I was already thinking I would add the latter at some point. The former may be useful as well.
The error message when setting the preference to "suspend" in 6 and later could be better.
The current message is "The Suspend ActionPreference value is reserved for future use and is not supported at this time. For more information about preference variables, see the Help topic, "about_Preference_Variables."" What do you think is missing from that message?
It's not so much missing, it's a tautology (Reserved for the future means not supported now) and back to front, it is there for legacy reasons. "Suspend is no longer supported" or if it might return "Suspend is not supported in this version of PowerShell" is shorter and clearer.
"At this time" is usually filler as well - it's technically wrong, it isn't a facet of the day on which you run it but the version - but leaves the question of when will it be supported.
The message printed by write-debug only appears when execution returns from the debugger, it should really appear first. .
This is by design.
PowerShell breaks into the debugger the moment the message is created so that you can look around at that point. Having it break into the debugger once the message is written to the host means unwinding the stack more and so you may lose some visibility on what was going on.
That said, in addition to showing the breakpoint line, we could consider showing the message text or some details about the trigger object (which is just an ErrorRecord, Exception, DebugRecord, etc.) when we enter the debugger based on a message, so that users see the stream message that triggered the breakpoint.
That would be ideal. If I have if (something involving $x and $y) { Write-debug "X is now $x and Y is $Y"}
seeing the values which dropped me into the debugger is a plus :-) EDIT
I was just thinking I might write code as
if ($myInvocation.boundparameters.debug -and something involving $x and $y) {
Write-host "X is now $x and Y is $Y"
wait-debugger
}
i.e. still use the debug switch never write-debug.... /EDIT
The debugger doesn't have the equivalent of "yes to all" in inquire, but as a work-round setting $debugpreference in the debugger sets it for the local scope, which is OK.
You're right. There are more things that could be done here, such as:
continue without breaking on other Error/Debug/etc. messages
making the detach (d) debugger command work for local script debugging as a way to tell PowerShell to disable the debugger until the current execution completes, running the command to completion without other breakpoints being triggered.
I was already thinking I would add the latter at some point. The former may be useful as well.
Agree. The first thing I tried was detaching the debugger and it says no :-)
There's one other thing I forgot to mention that I have planned. I wrote my DebugPx module with its Enter-Debugger command around the same time that the PowerShell Team wrote Wait-Debugger. One key feature that Enter-Debugger offered over Wait-Debugger is a scriptblock parameter that is used as a condition. It also has a string -Message parameter so that a specific message gets shown in the debugger when it enters a breakpoint based on a condition.
It is my intention to bring forward the functionality I've built-up in that module into PowerShell itself as native functionality. I've outlined that plan in #10448. I'd appreciate your thoughts on that plan as well James O'Neill (@jhoneill), because I think between the functionality it provides, and with scriptblock support in ActionPreference parameters as described in PowerShell/PowerShell-RFC#219, those would be better suited for the conditional debugging scenario you highlight in your edit above.
Activity
vexx32 commentedon Oct 23, 2019
Kirk Munro (@KirkMunro) can probably explain it much better than I'm able to, since he wrote all that fun code. 😊
The short version (probably missing a good deal of context myself, but what I know atm) is:
-Debugwas generally very unusable for the way most folks were wanting to use it, and completely unusable in CI environments, where ostensibly a lot of folks could stand to use it more.Things like
-ErrorAction Breakor$debugActionPreference = 'Break'were added to actually drop into the debugger on error or debug when you wanted to, but most folks were generally finding-Debugfairly unusable with the constant prompting.rjmholt commentedon Oct 23, 2019
See #8195
KirkMunro commentedon Oct 23, 2019
James O'Neill (@jhoneill) Good questions. Here are the answers in no particular order:
ActionPreference.Suspendwas for workflows and workflows only. We don't have workflows anymore, ergo, noActionPreference.Suspendsupport. We're still keeping the enumeration around, but it's reserved for future use at this time. I'm just calling that out since we're talking a little aboutSuspendas well asActionPreferencehere.The
Suspendoption in the handling ofActionPreference.Inquireis different thanActionPreference.Suspend. In the context of theInquireprompt,Suspenddrops you into a nested prompt. Nested prompts offered a way to do some inspection in PowerShell in v1, before PowerShell had a debugger. When it comes to debugging, today they offer much less value than the built-in debugger support. See also ActionPreference.Inquire is inconsistent and needs some redesign #9755.ActionPreference.Debugwas always about outputting debug messages. In PowerShell v1, when we didn't have a debugger, it also provided a way to get into a nested prompt so that you could look around and troubleshoot some things. It was not an actual debugger though -- you would be in a nested prompt (different scope), and you couldn't step through code, look at the code you were debugging using a debugger command, etc.Given the very limited usefulness of entering a nested prompt vs actually debugging, we added
ActionPreference.Breakfor those times when you want to break into a debugger and troubleshoot. This is what you should use if you want to enter the debugger and troubleshoot something.Further, since
Write-Debugwould result in interactive prompting, users who wanted to output messages in PowerShell that were not shown by default would always useWrite-Verbose, but that's not a great model, and has resulted in too much messaging being pumped through theVerbosestream.Verbosemessages are for extra messages that should help an end user figure out what is going wrong when something isn't working.Debugmessages are for extra messages that should help a developer figure out exactly what is happening when something is going wrong with a script or command they authored that is being run on another system.To sum up:
-DebugVerboseand one forDebug)ActionPreference.Break-ErrorAction Break)In both cases,
ActionPreference.Inquirestill exists, but is of questionable usefulness (again, see the discussion on #9755).Other items related to this discussion that you may want to be aware of:
Add VerboseAction, DebugAction, ProgressAction, VerboseVariable, DebugVariable, and ProgressVariable common parameters #10238 - this PR adds
-DebugAction,-DebugVariable,-VerboseAction,-VerboseVariable,-ProgressAction, and-ProgressVariable. These common parameters bring consistency to the common parameter set for handling messages. Once this is merged, if you want something like the old-Debug/ActionPreference.Inquirebehaviour, you could simply invoke a command with-DebugAction Inquire.Support ScriptBlocks in
-*Actioncommon parameters and*Preferencevariables to process errors and messages PowerShell-RFC#219 - this RFC proposes addingScriptBlocksupport to-*Actioncommon parameters, and$*Actionpreference variables, so that what they do can be decided on at runtime based on the actual*RecordorExceptionthat caused theScriptBlockto be invoked. That will allow people to break into the debugger when a certain type of message is generated, but only if it has specific properties (e.g. certain exception type, or error ID, or debug message string).jhoneill commentedon Oct 24, 2019
Thanks all (esp Kirk Munro (@KirkMunro)) for the detail. I was checking something I'd written a while back and found the behaviour had changed. I rarely use write-debug for exactly the reasons given as a rationale for the change :-) so I hadn't spotted it before.
Initially I didn't think
-debugas "super verbose" was a good idea, but having read the links above (Kirk again) it makes more sense than the other options. Inquire is of limited use, especially as it doesn't offer to drop into debug, only the nested prompt, and the number of times we need<<message>> Stop or Continue ?messages as part of debugging is small.The more I think about it the more its seems any problem here is that this change is so long overdue. I'm assuming other have grown used to something has worked, but quite poorly, so when it is made to work better, the change jars. Now I've read the docs, I think that's OK.
3 observations
But since the question is answered, and there is no bug so I'm going to close this issue.
KirkMunro commentedon Oct 24, 2019
The current message is "The Suspend ActionPreference value is reserved for future use and is not supported at this time. For more information about preference variables, see the Help topic, "about_Preference_Variables."" What do you think is missing from that message?
This is by design.
PowerShell breaks into the debugger the moment the message is created so that you can look around at that point. Having it break into the debugger once the message is written to the host means unwinding the stack more and so you may lose some visibility on what was going on.
That said, in addition to showing the breakpoint line, we could consider showing the message text or some details about the trigger object (which is just an
ErrorRecord,Exception,DebugRecord, etc.) when we enter the debugger based on a message, so that users see the stream message that triggered the breakpoint.You're right. There are more things that could be done here, such as:
detach (d)debugger command work for local script debugging as a way to tell PowerShell to disable the debugger until the current execution completes, running the command to completion without other breakpoints being triggered.I was already thinking I would add the latter at some point. The former may be useful as well.
jhoneill commentedon Oct 24, 2019
It's not so much missing, it's a tautology (Reserved for the future means not supported now) and back to front, it is there for legacy reasons. "Suspend is no longer supported" or if it might return "Suspend is not supported in this version of PowerShell" is shorter and clearer.
"At this time" is usually filler as well - it's technically wrong, it isn't a facet of the day on which you run it but the version - but leaves the question of when will it be supported.
That would be ideal. If I have
if (something involving $x and $y) { Write-debug "X is now $x and Y is $Y"}seeing the values which dropped me into the debugger is a plus :-)
EDIT
I was just thinking I might write code as
i.e. still use the debug switch never
write-debug..../EDIT
Agree. The first thing I tried was detaching the debugger and it says no :-)
KirkMunro commentedon Oct 24, 2019
There's one other thing I forgot to mention that I have planned. I wrote my
DebugPxmodule with itsEnter-Debuggercommand around the same time that the PowerShell Team wroteWait-Debugger. One key feature thatEnter-Debuggeroffered overWait-Debuggeris ascriptblockparameter that is used as a condition. It also has a string-Messageparameter so that a specific message gets shown in the debugger when it enters a breakpoint based on a condition.It is my intention to bring forward the functionality I've built-up in that module into PowerShell itself as native functionality. I've outlined that plan in #10448. I'd appreciate your thoughts on that plan as well James O'Neill (@jhoneill), because I think between the functionality it provides, and with
scriptblocksupport inActionPreferenceparameters as described in PowerShell/PowerShell-RFC#219, those would be better suited for the conditional debugging scenario you highlight in your edit above.