Powershell: Too many different -Scope parameters

Created on 13 Jun 2019  路  15Comments  路  Source: PowerShell/PowerShell

Currently there are several different uses of -Scope as a parameter in core PowerShell modules:

  • As a string to identify a PowerShell invocation scope (e.g. when using cmdlets that work with aliases, variables, PSDrives, and modules)
  • As a string to identify the profile to work with (e.g. when working with Package Management commands, you can specify CurrentUser or AllUsers, and now when working with experimental features)
  • As an ExecutionPolicyScope enumeration to identify the execution policy scope (e.g. when working with the *-ExecutionPolicy cmdlets)

Personally I've found it confusing when I see that parameter name, assume it means one thing, and then find out in the documentation it means something else. Before this confusion continues, especially within core PowerShell modules, perhaps it would be better if at least some of these used a more explicit parameter name, with -Scope as an alias for backward compatibility.

For example, in package management and experimental features, -UserScope would be more appropriate than simply using -Scope. For *-ExecutionPolicy cmdlets, -PolicyScope would be more appropriate and accurate than simply using -Scope.

Thoughts?

Area-Cmdlets Committee-Reviewed Issue-Question Resolution-Answered

Most helpful comment

@PowerShell/powershell-committee reviewed this (@BrucePay included) and we don't feel anything we do here is going to add much value:

  • Adding a descriptor to -Scope is going to be repetitive with the noun (e.g. -ModuleScope or -InstallationScope for Install-Module doesn't seem helpful)
  • Where disambiguation is needed between two scope concepts, it's perfectly fine to use a prefix for that disambiguation
  • -For is a "fluent" parameter that might read better, but it's not a pattern we've used often in PowerShell parameters, and it's not any less ambiguous than -Scope
  • Tab completion works fine for all the -Scope values across the cmdlets
  • There was 50/50 agreement in the room between whether using -For for -Force was a valid concern. I personally use -fo interactively every day, and this would drive me crazy (especially on Install-Module).

All 15 comments

Given these are parameters, we can change the parameter name and assign the alias Scope to each of these both as a shorthand and for backwards compatibility. I see no reason not to clarify the meaning of these parameters, it's something that's bothered me for quite a while.

@KirkMunro

-UserScope would be more appropriate than simply using -Scope.

Interesting. Personally I find -Scope user much more readable than -UserScope. Also, as a parameter argument, you can easily pass it as a value without having to splat.

@vexx32

we can change the parameter name and assign the alias Scope to

You can't use aliases like that. You can't alias -UserScope to -Scope User.

see no reason not to clarify the meaning of these parameters,

That's what documentation is for. Is there a problem with the current docs? If so, please open a docs bug. Thanks.

Hmm. It's not clear, but I read it as saying "we should use -UserScope as a direct replacement for -Scope for that cmdlet; for example -UserScope User or -UserScope System (or whatever that one is, I gotta say I don't install a whole lot system wide).

The name might want to be changed if that is the case, though... maybe -ModuleScope or something.

@bpayette That's not what I meant.

My issue is that there are three distinct parameter types for -Scope parameters among modules that ship with PowerShell, and when I see -Scope I may need to go to the docs to see what it's for when it would be better if I didn't have to.

If the *-ExecutionPolicy cmdlets instead had a -PolicyScope parameter (with an alias of Scope for backward compatibility), and if the PowerShellGet/PackageManagement cmdlets and the *-ExperimentalFeature cmdlets instead had a -UserScope parameter (with an alias of Scope for backward compatibility), then the parameters would be more self-explanatory.

Does that make more sense? Maybe the part that confused you was the -UserScope parameter name proposal. I suppose it could be called -ProfileScope instead, but having it just called -Scope by default with values of CurrentUser and AllUsers when other cmdlets in PowerShell have -Scope parameters that take values such as Global, Local, Script, or a numeric value, that difference in definition of scope (the difference between commands, not within one command) is a confusion point that could be eliminated.

Case in point: when I was looking at *-ExperimentalFeature cmdlets and I saw -Scope, I initially presumed that it was referring to a PowerShell invocation scope where you could enable the feature, and didn't realize it was about enabling those features for the current user or for all users on the local system instead.

Historical reasoning:

Set-ExecutionPolicy -scope ...

Scope in this case is clearly qualified by the noun so -PolicyScope is redundant

Set-Variable -Scope ...

Again, -Scope is clearly qualified by the noun making -VariableScope redundant.

And then it all goes off the rails with Install-Module:

Install-Module -Scope ...
Import-Module -Scope ...

This is extremely unfortunate because here the qualifying noun doesn't provide sufficient context. Maybe something like

Install-Module -Repository ...

would be more semantically significant.

take values such as Global, Local, Script, or a numeric value is a confusion point that could be eliminated.

For Import-Module -Scope ... , Get-Variable -Scope ... and $global:foo = ... , in all cases, the word "scope" is referring to exactly the same thing: the activation stack of the currently running script. The use of numeric values allows more specific non-local references than "script" or "global".

with *-ExperimentalFeature... thought it was referring to a PowerShell invocation scope where you could enable the feature, and didn't realize it was about enabling those features for the current user or for all users on the local system instead

I totally get that. This should probably just be fixed. Maybe -EnableFor ? Or just -For ? Install-Module -For CurrentUser would work too as would Set-ExecutionPolicy -For process.

I 鉂わ笍 the -For parameter name suggestion. That's very expressive! I've updated an RFC I have open proposing optional features to use that parameter name because it makes the commands self-documenting.

I also like that parameter name for *-ExecutionPolicy, *-ExperimentalFeature, and the PowerShellGet/PackageManagement commands. Thanks for that suggestion @BrucePay!

Aside: You have two GitHub accounts that you seem to use on posts interchangeably. Is there one you would prefer we use when we @-mention you?

@SteveL-MSFT: This should be a fairly quick decision to make for or against this in the Committee. Could you table this at a meeting? If the Committee buys in, I'll submit the PRs.

The tl;dr of this is:

PowerShell uses "scope" to refer to the activation stack of the currently running script. Because of that, a -Scope parameter name on Import-Module, Get-Variable, etc. makes sense. There are other uses of -Scope as a parameter name that cause confusion: Enable-ExperimentalFeature and Disable-ExperimentalFeature, for example, as well as commands in PowerShellGet/PackageManagement and the Get-/Set-ExecutionPolicy cmdlets. I think we should consider changing the name of -Scope in those commands to something more appropriate, with -Scope as an alias for backwards compatibility. @BrucePay's suggestion of -For is a really good alternative parameter name that makes commands self-documenting in all of those cases.

I'm not a fan of the -For idea because I use -For interactively for -Force. Also, while this is "fluent" in nature, a preposition doesn't quite fit the PowerShell idiom for parameter names IMO. I'm certainly up for changing the parameter name on Enable/Disable-ExperimentalFeature.

@rkeithhill Prepositions are already in use as parameter names in PowerShell commands. Some common examples that come to mind are the -From and -To parameters in Send-MailMessage, or the -Before and -After parameters in Get-Job.

Fair enough. I guess down the road I'd still like to still be able to recognize the language/commands. I'm all for high value additions and strategic changes but changing things that have existed for a decade or more to make it "slightly better" ... yeah, I'm not a fan of that.

Not all of these commands have been there for a decade or more, and among those discussed here, the commands that are a dozen years old are not the ones where changes are being proposed here, aside from Get-/Set-ExecutionPolicy which are usually just fire-and-forget commands.

I look at issues like this as something that wasn't readily apparent early on, but that later became more of a problem due to additions to the language, at which time it makes sense to at least question the current direction, and perhaps change it based on the current landscape of features/commands.

Plus, to speak to the "slightly better" comment and give some background behind where this discussion started, I have an RFC open for commands for use with optional features. In an earlier version of the draft, I was looking at using a -Scope parameter, but in those cmdlets that's very confusing because they have two notions of scope: the users for whom they are enabled/disabled or by default (e.g. CurrentUser or AllUsers) _and/or_ the activation stack in which they are enabled or disabled. It's during the authoring of that RFC that I ran into this parameter name challenge, and to maintain discoverability and consistency started to question the -Scope name more broadly.

This is not just a trivial I-have-nothing-better-to-do-with-my-time-so-let's-go-fix-something-that-isn't-important-to-make-something-slightly-better scenario.

I have an RFC open for commands for use with optional features.

And it's a great conversation to have for new commands. I'm just not so keen on the "let's also change well-established commands for consistency" aspect of this. BTW I don't consider the ExperimentalFeature commands to be well-established - so they're fair game for changes.

Scope as a parameter to me makes sense & changing this in all the areas seems to not provide all that much benefit whilst adding more unnecessary confusion, especially as now you are moving into the realms of parameter naming guidance, whereas good Parameter Help should be where people go to learn and understand what the parameter means more than it's simple name, along with good examples.

Also Scope is used heavily in Az Commands for a manner of different contextual usecases.

I'm siding with @rkeithhill on this as to me doesn't seem to add value to either new or existing scripters and would in fact likely cause more confusion than anything else.

@PowerShell/powershell-committee reviewed this (@BrucePay included) and we don't feel anything we do here is going to add much value:

  • Adding a descriptor to -Scope is going to be repetitive with the noun (e.g. -ModuleScope or -InstallationScope for Install-Module doesn't seem helpful)
  • Where disambiguation is needed between two scope concepts, it's perfectly fine to use a prefix for that disambiguation
  • -For is a "fluent" parameter that might read better, but it's not a pattern we've used often in PowerShell parameters, and it's not any less ambiguous than -Scope
  • Tab completion works fine for all the -Scope values across the cmdlets
  • There was 50/50 agreement in the room between whether using -For for -Force was a valid concern. I personally use -fo interactively every day, and this would drive me crazy (especially on Install-Module).
Was this page helpful?
0 / 5 - 0 ratings