Skip to content

Change in behaviour of -Debug common parameter #10873

Closed

Description

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 ?

Activity

  1. added
    Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get a
    on Oct 23, 2019
  2. vexx32 commented on Oct 23, 2019

    @vexx32
    Collaborator

    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.

  3. rjmholt commented on Oct 23, 2019

    @rjmholt
    Collaborator

    See #8195

  4. KirkMunro commented on Oct 23, 2019

    @KirkMunro
    Contributor

    James O'Neill (@jhoneill) Good questions. Here are the answers in no particular order:

    1. 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.

    2. 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.

    3. 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:

    1. 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.Inquire behaviour, you could simply invoke a command with -DebugAction Inquire.

    2. 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).

  5. jhoneill commented on Oct 24, 2019

    @jhoneill
    Author

    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.

  6. KirkMunro commented on Oct 24, 2019

    @KirkMunro
    Contributor
    • 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.

  7. jhoneill commented on Oct 24, 2019

    @jhoneill
    Author
    • 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 :-)

  8. KirkMunro commented on Oct 24, 2019

    @KirkMunro
    Contributor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Issue-Questionideally support can be provided via other mechanisms, but sometimes folks do open an issue to get aResolution-AnsweredThe question is answered.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions