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
Feature Request: Variable Parameter with switch-like capability #12104
What I'm looking for is the ability to use a parameter to pass a variable, yet be able to act similar to a switch. Essentially...
No parameter: PS>FunctionName
Or, parameter used like a switch where it will utilize a default value PS>FunctionName -Parameter
Or, parameter used with a specified override to the default value PS>FunctionName -Parameter 123
The idea is that I have a need for a function to accept multiple switch style inputs to say enable/disable, use/don't-use a particular feature. To that end a switch parameter works fine. However, many of the parameters are not only a true/false but also a variable, and I want to be able to provide the user a way to override the default value. A second parameter could be specified and required with dynamic parameters, to which the the input might look as follows...
PS>FunctionName -Parameter -ParameterOverride 123
But, this is clunky at best and considering the function I'm presently trying to work with has need for 8 parameters of this style it's down right ugly to use from the users perspective.
Hmm. Actually, that's only really a good solution if you have a specific set of acceptable values. If you have others... hmm. Yeah, okay, not sure. Depends on the exact requirements -- you can, for example, check $PSBoundParameters to verify if the value was actually passed deliberately or comes from some default parameter value you have set... and you can of course restrict input types.
What I've tried so far with limited success was this...
Function test {
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false)]
[ValidateRange(1,25)]
[Int]
$OptionalNumber = 1
)
if($PSBoundParameters.keys -contains "OptionalNumber"){
Write-Output "The optional number parameter is present"
Write-Output "The Optional Number is: $OptionalNumber"
}else{Write-Output "The optional number parameter was not specified"}
}
that works with running PS>test
or running PS>test -OptionalNumber 4
but fails when running PS>test -OptionalNumber
I've tried (and failed) with all kinds of combinations of [ValidationScript()], [AllowNull()], [Nullable[int]] in an attempt to modify the parameter requirements, but every time it complains that there must be a value passed in when the "-OptionalNumber" parameter is present.
Yeah. The default value will be used whenever the parameter is not specified at all.
Is there an important distinction here where you need the parameter to be specified for some reason, even though the default value will be used anyway?
Yeah. The default value will be used whenever the parameter is not specified at all.
Is there an important distinction here where you need the parameter to be specified for some reason, even though the default value will be used anyway?
Basically, I want the presence (or lack thereof) of the parameter to be triggered like a switch parameter. If it's not there, just ignore the fact that it even has a default value set. However, if the parameter is present, then use whatever value the user specifies, and if no value is specified, use the default value.
This isn't how I'm needing to use it (my case is a bit too much to explain easily), but imagine that you have a parameter that you call "$Log". You use that parameter to say that you want your function to enable a logging/transcript function. You have a default location already baked in... be it a specific or relative path.. but you want to give them the option to specify their own path.
So this just runs the function without logging... PS>ExampleFunction
This would run with logging to the default location... PS>ExampleFunction -Log
And this would run with logging to a specific location... PS>ExampleFunction -Log C:\Temp\log.txt
Again.. it is just an example of how it could be used. My use case is different but similar.
Let me illustrate the proposal with a real-world example of such a parameter from the GNU sed Unix utility, whose -i option (for creating a backup of the input file) works as follows:
If -i isn't specified at all, no backup is created.
If only-i is specified, a backup file with default extension .bak is created.
If the user wishes to specify a different extension, they can pass an optional value to -i; e.g., -i.org.
For this to work syntactically in Powershell, the optional value, if specified, would have to be attached to the parameter name, with : as the separator (update: though there may be whitespace between the : and the argument):
-MakeBackup:".org"
This is how it already works for [switch] parameters, and this attachment is necessary to avoid ambiguity between optional parameter values and subsequent positional arguments.
Reacted by Rain Sallow (/u/ta11ow), Craig Haydock and RalfReddings
It's the ':' on the end of the switch that tells parser that the next argument binds to the switch parameter so syntactically the desired behavior could be implemented. However if this is generalized, how will the script distinguish between absent, present and present with a value? You'd have to encapsulate the value in a "magic" class containing the value along with the present flag. (This is more or less what which does.) This seems unnecessarily complicated.
Reacted by Patrick Meinecke and Rain Sallow (/u/ta11ow)
Every time I've wished for this type of parameter, I realized I was trying to fit too much into a single command. The best way to handle this currently is one of these:
Have a switch that just enables the behavior, this parameter would belong to AllParameterSets and also BehaviorNameSet. Have a separate optional parameter to specify the argument which only belongs to BehaviorNameSet
Have a switch that enables the behavior, this parameter only belongs to BehaviorNameDefaultSet. Have a separate mandatory parameter to specify the argument which only belongs to BehaviorNameExplicitArgSet. Default parameter set would be AllParameterSets to make both optional
Both of those solutions are heavy on parameter sets. If you find that you're running into trouble related to the number of sets you have, consider splitting the functionality into separate commands. While this would probably be a common request, I think that ultimately the lack of this syntax leads to better design (for a PowerShell command anyway, not disparaging monolith CLI executables).
I also agree with Bruce Payette (@bpayette), usage of this type of parameter in a resilient way would be pretty verbose (if even possible).
Reacted by Rain Sallow (/u/ta11ow), Brian Scholer and Keith Hill
Good point about the whitespace, Bruce Payette (@bpayette): It's not the whitespace, it is the : that constitutes the attachment, and that : is all that's needed to unambiguously designate the argument as belonging to the parameter - as is already the case with and necessary for [switch] parameters, generalizing the logic of which is the gist of this proposal.
However if this is generalized, how will the script distinguish between absent, present and present with a value?
In order: -not $PSBoundParameters.ContainsKey('zork'), default value, bound value.
Have a switch that just enables the behavior (...). Have a separate optional parameter
Avoiding the ceremony and awkwardness of having to say -PleaseDo and -IfyouDoThenWith WithValue instead of just -PleaseDo:WithValue (with -PleaseDo with a default value typically being enough) is what this proposal is about.
I get that this is amounts to a new concept (though not technically, given that [switch] already works this way), which is always challenging:
Users, if they're even aware of : as a parameter/argument separator at all, will have to understand that in the case of such optional-argument parameters they'll have to use it.
Then again, the relative obscurity of : may be a blessing in this case: start publicizing it in the context of this new feature, and recommend that it only be used for that.
We'll have to come up with a way of representing optional-argument parameters in the syntax diagrams (and, of course, implementation-wise in the parameter declaration, which could be as simple as [Parameter(ValueOptional)]).
I personally think it's worth doing, but I get that it introduces additional complexity, and that it would require a focused effort to publicize and properly document the new feature.
Have a switch that just enables the behavior (...). Have a separate optional parameter
Avoiding the ceremony and awkwardness of having to say -PleaseDo and -IfyouDoThenWith WithValue instead of just -PleaseDo:WithValue (with -PleaseDo with a default value typically being enough) is what this proposal is about.
But how many scenarios are there where a better design wouldn't be Please-Do WithValue?
Also personally I'd say -PleaseDo:WithValue is more awkward. I know that syntax already exists, but thankfully the use cases for it are pretty infrequent. Objectively less ceremony, but the awkwardness of either syntax is subjective.
I'm increasingly making use of hiding outdated / resolved comments in order to keep threads short(er), and I often update the initial post with salient information discovered later and / or try to summarize a debate succinctly in a later comment.
But the overall length is still a problem, and I wish there were some protocol for arriving at an agreed-upon final form of a proposal or concise summary of a debate- short of authoring an RFC, which often isn't appropriate (yet) and, it seems, is where ideas go to die - that doesn't require future readers to read the entire history.
Having a shared, perhaps even documented understanding of how to use emoji would help too, though, at least based on the limited set of standard emoji offered by the site, I guess it's now down to the question whether to use 👎or 😕to signal one's final yay-or-nay stance (even though I bristled at it initially, I think the former is preferable).
Reacted by Patrick Meinecke, Rain Sallow (/u/ta11ow) and Brian Scholer
I would love for this to work as you describe if only switch were to accept more than just $true/$false. If the switch parameter were to allow decoration as any variable type beyond Boolean, this would solve the problem I have at hand....
PS > function foo { param( [switch] $zork) $zork}
PS > foo
IsPresent
---------
False
PS > foo -zork
IsPresent
---------
True
PS > foo -zork: 4
foo : Cannot process argument transformation on parameter 'zork'. Cannot convert the "4" value of type "System.Int32" to type "System.Management.Automation.SwitchParameter".
At line:1 char:12
+ foo -zork: 4
+ ~
+ CategoryInfo : InvalidData: (:) [foo], ParameterBindingArgumentTransformationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,foo
The irony being that switch as an alternative to using endless if/else statements handles anything you can thing of to throw at it. But as a parameter can only handle $true/$false.
Craig Haydock (@chaydock), note that the [switch] parameter type and the switch statement only happen to share the same name, but are otherwise unrelated.
I think we've already established the desired behavior and hinted at possible implementations.
Implementing this feature is definitely possible, but I don't think it's useful to further discuss implementation details until a decision is made on if this feature should be supported at all, which, of course, may be negative - or may never come.
I was disappointed to learn that this isn't currently possible, though I can understand why given PowerShell would have a hard time distinguishing between the argument of a positional parameter and an optional argument for a parameter like this one.
However, there already is syntax for parameters like -Debug:$true, so I think the best solution would be to use this colon-based syntax for a new ternary-type parameter that can accept both booleans and another data type, so you could easily do something like -Foo:'bar' (with $true assumed if there's no argument).
Reacted by RalfReddings
microsoft-github-policy-service commented on Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commented on Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commented on Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
Activity
vexx32 commentedon Mar 11, 2020
It's not exactly what you're after, but you could potentially utilise a
[ValidateSet()]to make this easier to work with.chaydock commentedon Mar 11, 2020
How exactly would you employ a ValidateSet to solve this problem?
vexx32 commentedon Mar 11, 2020
Hmm. Actually, that's only really a good solution if you have a specific set of acceptable values. If you have others... hmm. Yeah, okay, not sure. Depends on the exact requirements -- you can, for example, check
$PSBoundParametersto verify if the value was actually passed deliberately or comes from some default parameter value you have set... and you can of course restrict input types.I was thinking something along these lines:
chaydock commentedon Mar 11, 2020
What I've tried so far with limited success was this...
that works with running
PS>testor running
PS>test -OptionalNumber 4but fails when running
PS>test -OptionalNumberI've tried (and failed) with all kinds of combinations of [ValidationScript()], [AllowNull()], [Nullable[int]] in an attempt to modify the parameter requirements, but every time it complains that there must be a value passed in when the "-OptionalNumber" parameter is present.
vexx32 commentedon Mar 11, 2020
Yeah. The default value will be used whenever the parameter is not specified at all.
Is there an important distinction here where you need the parameter to be specified for some reason, even though the default value will be used anyway?
chaydock commentedon Mar 11, 2020
for what it's worth, there was some discussion on this already on StackOverflow.com
https://stackoverflow.com/questions/60459934/use-function-parameter-as-both-a-variable-and-switch
https://stackoverflow.com/questions/58838941/powershell-special-switch-parameter
chaydock commentedon Mar 11, 2020
Basically, I want the presence (or lack thereof) of the parameter to be triggered like a switch parameter. If it's not there, just ignore the fact that it even has a default value set. However, if the parameter is present, then use whatever value the user specifies, and if no value is specified, use the default value.
This isn't how I'm needing to use it (my case is a bit too much to explain easily), but imagine that you have a parameter that you call "$Log". You use that parameter to say that you want your function to enable a logging/transcript function. You have a default location already baked in... be it a specific or relative path.. but you want to give them the option to specify their own path.
So this just runs the function without logging...
PS>ExampleFunctionThis would run with logging to the default location...
PS>ExampleFunction -LogAnd this would run with logging to a specific location...
PS>ExampleFunction -Log C:\Temp\log.txtAgain.. it is just an example of how it could be used. My use case is different but similar.
mklement0 commentedon Mar 11, 2020
Let me illustrate the proposal with a real-world example of such a parameter from the GNU
sedUnix utility, whose-ioption (for creating a backup of the input file) works as follows:If
-iisn't specified at all, no backup is created.If only
-iis specified, a backup file with default extension.bakis created.If the user wishes to specify a different extension, they can pass an optional value to
-i; e.g.,-i.org.For this to work syntactically in Powershell, the optional value, if specified, would have to be attached to the parameter name, with
:as the separator (update: though there may be whitespace between the:and the argument):This is how it already works for
[switch]parameters, and this attachment is necessary to avoid ambiguity between optional parameter values and subsequent positional arguments.bpayette commentedon Mar 13, 2020
Actually there is no need for "attachment". This works fine:
It's the ':' on the end of the switch that tells parser that the next argument binds to the switch parameter so syntactically the desired behavior could be implemented. However if this is generalized, how will the script distinguish between absent, present and present with a value? You'd have to encapsulate the value in a "magic" class containing the value along with the
presentflag. (This is more or less what which does.) This seems unnecessarily complicated.SeeminglyScience commentedon Mar 13, 2020
Every time I've wished for this type of parameter, I realized I was trying to fit too much into a single command. The best way to handle this currently is one of these:
Have a switch that just enables the behavior, this parameter would belong to AllParameterSets and also
BehaviorNameSet. Have a separate optional parameter to specify the argument which only belongs toBehaviorNameSetHave a switch that enables the behavior, this parameter only belongs to
BehaviorNameDefaultSet. Have a separate mandatory parameter to specify the argument which only belongs toBehaviorNameExplicitArgSet. Default parameter set would be AllParameterSets to make both optionalBoth of those solutions are heavy on parameter sets. If you find that you're running into trouble related to the number of sets you have, consider splitting the functionality into separate commands. While this would probably be a common request, I think that ultimately the lack of this syntax leads to better design (for a PowerShell command anyway, not disparaging monolith CLI executables).
I also agree with Bruce Payette (@bpayette), usage of this type of parameter in a resilient way would be pretty verbose (if even possible).
mklement0 commentedon Mar 13, 2020
Good point about the whitespace, Bruce Payette (@bpayette): It's not the whitespace, it is the
:that constitutes the attachment, and that:is all that's needed to unambiguously designate the argument as belonging to the parameter - as is already the case with and necessary for[switch]parameters, generalizing the logic of which is the gist of this proposal.In order:
-not $PSBoundParameters.ContainsKey('zork'), default value, bound value.No magic needed at all.
mklement0 commentedon Mar 13, 2020
Patrick Meinecke (@SeeminglyScience):
Avoiding the ceremony and awkwardness of having to say
-PleaseDoand-IfyouDoThenWith WithValueinstead of just-PleaseDo:WithValue(with-PleaseDowith a default value typically being enough) is what this proposal is about.I get that this is amounts to a new concept (though not technically, given that
[switch]already works this way), which is always challenging:Users, if they're even aware of
:as a parameter/argument separator at all, will have to understand that in the case of such optional-argument parameters they'll have to use it.:may be a blessing in this case: start publicizing it in the context of this new feature, and recommend that it only be used for that.We'll have to come up with a way of representing optional-argument parameters in the syntax diagrams (and, of course, implementation-wise in the parameter declaration, which could be as simple as
[Parameter(ValueOptional)]).I personally think it's worth doing, but I get that it introduces additional complexity, and that it would require a focused effort to publicize and properly document the new feature.
SeeminglyScience commentedon Mar 16, 2020
But how many scenarios are there where a better design wouldn't be
Please-Do WithValue?Also personally I'd say
-PleaseDo:WithValueis more awkward. I know that syntax already exists, but thankfully the use cases for it are pretty infrequent. Objectively less ceremony, but the awkwardness of either syntax is subjective.3 remaining items
mklement0 commentedon Mar 16, 2020
SeeminglyScience commentedon Mar 17, 2020
mklement0 commentedon Mar 17, 2020
SeeminglyScience commentedon Mar 17, 2020
mklement0 commentedon Mar 17, 2020
Both excellent points, Patrick Meinecke (@SeeminglyScience).
I'm increasingly making use of hiding outdated / resolved comments in order to keep threads short(er), and I often update the initial post with salient information discovered later and / or try to summarize a debate succinctly in a later comment.
But the overall length is still a problem, and I wish there were some protocol for arriving at an agreed-upon final form of a proposal or concise summary of a debate- short of authoring an RFC, which often isn't appropriate (yet) and, it seems, is where ideas go to die - that doesn't require future readers to read the entire history.
Having a shared, perhaps even documented understanding of how to use emoji would help too, though, at least based on the limited set of standard emoji offered by the site, I guess it's now down to the question whether to use 👎or 😕to signal one's final yay-or-nay stance (even though I bristled at it initially, I think the former is preferable).
chaydock commentedon Mar 22, 2020
I would love for this to work as you describe if only switch were to accept more than just $true/$false. If the switch parameter were to allow decoration as any variable type beyond Boolean, this would solve the problem I have at hand....
The irony being that switch as an alternative to using endless if/else statements handles anything you can thing of to throw at it. But as a parameter can only handle $true/$false.
mklement0 commentedon Mar 22, 2020
Craig Haydock (@chaydock), note that the
[switch]parameter type and theswitchstatement only happen to share the same name, but are otherwise unrelated.I think we've already established the desired behavior and hinted at possible implementations.
Implementing this feature is definitely possible, but I don't think it's useful to further discuss implementation details until a decision is made on if this feature should be supported at all, which, of course, may be negative - or may never come.
God-damnit-all commentedon Dec 6, 2021
I was disappointed to learn that this isn't currently possible, though I can understand why given PowerShell would have a hard time distinguishing between the argument of a positional parameter and an optional argument for a parameter like this one.
However, there already is syntax for parameters like -Debug:$true, so I think the best solution would be to use this colon-based syntax for a new ternary-type parameter that can accept both booleans and another data type, so you could easily do something like
-Foo:'bar'(with $true assumed if there's no argument).microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 16, 2023
This issue has not had any activity in 6 months, if this is a bug please try to reproduce on the latest version of PowerShell and reopen a new issue and reference this issue if this is still a blocker for you.
microsoft-github-policy-service commentedon Nov 23, 2023
This issue has been marked as "No Activity" as there has been no activity for 6 months. It has been closed for housekeeping purposes.
RalfReddings commentedon May 19, 2025
Please consider adressing this feature or issue. Its very much needed.