Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Propagate execution preferences beyond script module scope #221

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

KirkMunro
Copy link
Contributor

This RFC was originally proposed as part of a collection of RFCs in PR #187. I am separating those RFCs into separate PRs to better adhere to the RFC process.

@KevinMarquette
Copy link

I am surprised that this has been broken for as long as hit has. I find that this issue makes -WhatIf a very dangerous parameter. A module author should not need to be aware of the fact that they command they are calling is in a binary module or a script module. But to correctly implement SupportsShouldProcess, they absolutely must know when they are making calls to a script module so they know to call it with -WhatIf:$WhatIf or wrap it behind a call to $PSCmdlet.ShouldProcess.

The real danger is most people don't realize it works this way.

@vexx32
Copy link
Contributor

vexx32 commented Feb 29, 2020

Agreed. This issue renders every common parameter effectively unusable for script module authors whenever they call commands external to their modules because most authors will not understand why some commands work without issue and others completely ignore the requested preference.

I can only hope we can get it approved for a fix as soon as possible.

@bergmeister
Copy link

bergmeister commented Mar 6, 2020

Stumbled across this today as well when I refactored code into a common script module where as a result of that the $WhatIfPreference was not propagated any more to the function being called. This is a serious bug IMHO and I don't see how fixing this would break other people's code, even if someone relied on $WhatIfPreference actually not being propagated then it should be an easy fix anyway.

@vexx32
Copy link
Contributor

vexx32 commented Mar 6, 2020

@joeyaiello @SteveL-MSFT is this one one your guys' radar at all? 💖

@bwright86
Copy link

I am following the rabbit trail from Powershell\Powershell#4568, and am trying to solve this as well. I see DWyatt's "Get-CallerPreference" script, and am thinking of using something similar for now.

There is an edge case to this proposal that may need considering. I have a module with a cmdlet(Adv. Function), that contains verbose messages to call out information, and is called by other higher-level cmdlets a lot of times (possibly hundreds of times). When I do -verbose from the high-level cmdlets, I don't want these chatty verbose messages to be forwarded, so I use -Verbose:$false in the higher-level cmdlets, to disable this from happening. (TBH, I can't recall if -Verbose:$false is even necessary, but I use it.)

IMO, I think opting-out of passing these preferences would be useful. But by default, I would like to see "Calling cmdlets" pass their preferences onto the "Called cmdlets". Mostly, because there isn't a preferred/documented/best-practice way to make this work currently.

@vexx32
Copy link
Contributor

vexx32 commented Jun 24, 2020

@bwright86 I can see that potentially being useful, but I think at least as an initial implementation it would be preferable that it affect everything; as you note, those authors can selectively pick and choose which cmdlets' preference variables are passed along by simply manually overriding the -Verbose (etc) params when their function calls other functions.

I'm not sure a completely separate preference is necessary, but if it does end up being desirable I could see potentially something like an additional property in CmdletBinding to modify the behaviour would perhaps be one way to go about it.

@bwright86
Copy link

I agree with you, and I think what is being pointed out by this RFC and many SO questions, is that there isn't a good way to code the preferred way. So if this RFC goes forward, it would be nice to document the "opt-out" way for the use case i mentioned.

So I wasn't looking for anything to be implemented from my edge case, but maybe something to keep in mind, or integrate into the RFC language.

I think manually overriding the preference like you mentioned may be a good way around it, and calling it out in the CmdletBinding() attribute could be interesting.

As a side note, the issue I was facing today that caused me to go down this rabbit hole, was the -InformationAction variable. But it turns out that I was using a Write-Host in my lower-level cmdlet, and the documentation does call out that an Ignore flag can be used to filter these out. So more to learn on my side around this.

@joeyaiello joeyaiello added the WG-Engine core PowerShell engine, interpreter, and runtime label Jul 27, 2021
@bazilious
Copy link

I am surprised that such an old issue is not yet fixed. I have lost many hours to find why execution preferences do not propagate between modules. It's absolutely unacceptable that this thing happens.

@StewartRyanSony
Copy link

Just came across this while checking to ensure that my WhatIf preference would transfer to functions in a helper script. It seems that due to this issue they will not without extra code to explicitly transfer the preference.

The fact that the behavior is different between binary modules and script modules if very confusing and not what users will expect. It's been over 4 years. This should be fixed.

cbellee referenced this pull request in Azure/AzLoadBalancerMigration Feb 29, 2024
@BaconTentacles
Copy link

I finally went a slightly different and somewhat hacky route, using $PSDefaultParameterValues and wildcards on namespaced functions, so that they would be limited to the ones in my module.
So if I wrote a bunch of functions namespaced with MJL (Get-MJLThingy, New-MJLThingy, etc), I would just initialize those at the start of any calling script, like:

$PSDefaultParameterValues = @{ 
    "*-MJL*:Verbose" = { $PSBoundParameters['Verbose'] -or $VerbosePreference -eq 'Continue' } 
    "*-MJL*:WhatIf"  = { $PSBoundParameters['WhatIf'] -or $WhatIfPreference } 
}

The only down side is that you have to specify SupportsShouldProcess in any function where you want WhatIf to work, even if you're not doing any special checking in that function (and, say, passing things along to another function). But...it's a small price to pay compared to just sticking with dot-sourcing everything as .ps1 files.
Hack? Yes. Does it work? Also yes. It'll do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WG-Engine core PowerShell engine, interpreter, and runtime
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants