Here is the code that demonstrates the problem. The cmdlet Set-Location
has
the dynamic switch ReadOnly
if the provider is FileSystem
.
# provider that does not have the dynamic -ReadOnly
Set-Location env:
# case 1: works because we explicitly specify FileSystem
Get-ChildItem C:\ -ReadOnly
# case 2: fails even though we explicitly specify FileSystem
Get-ChildItem -ReadOnly C:\
Normally position of a switch parameter in a command does not matter. This not the case for a dynamic switch. The case 2 fails with the error:
Get-ChildItem : A parameter cannot be found that matches parameter name 'ReadOnly'.
What happens? I think that at the moment of dynamic parameters creation it is
not yet known that ReadOnly
is the switch. Thus, PowerShell treats it as a
regular parameter with its argument C:\
and C:\
therefore is not treated as
a positional parameter. As a result, Get-ChildItem
thinks that the location
is not specified and uses the current env:
. The provider Environment
does
not provide the dynamic switch ReadOnly
, so that finally the command fails
due to incorrect syntax, even though it is somewhat correct (the same command
works if the current provider is FileSystem
).
Questions:
The last question is more about user commands being developed with dynamic parameters. The problem originally was noticed and described as Invoke-Build Issue #4. For the moment this issue is just documented. But I am still interested in workarounds.
Conclusions
-ReadOnly:$true
Opened the bug: 960194
A positional parameter is a parameter denoted by one or more digits, other than the single digit 0 . Positional parameters are assigned from the shell's arguments when it is invoked, and may be reassigned using the set builtin command.
A positional parameter requires only that you type the arguments in relative order. The system then maps the first unnamed argument to the first positional parameter. The system maps the second unnamed argument to the second unnamed parameter, and so on. By default, all cmdlet parameters are named parameters.
Switch parameters. Switch parameters are parameters that take no parameter value. Instead, they convey a Boolean true-or-false value through their presence or absence, so that when a switch parameter is present it has a true value and when absent it has a false value.
Your understanding is exactly right.
The parameter binder is not documented well as it is extremely complex. The language specification (http://www.microsoft.com/en-us/download/details.aspx?id=36389) is the maybe the best documentation we have, but it is incomplete and I don't think covers this situation.
The only workaround I can think of is to specify the argument to the switch parameter, e.g.
Get-ChildItem -ReadOnly:$true C:\
Feel free to open a bug. It probably won't get fixed, but it at least gives the team a chance to discuss it.
I'd imagine the fix would be something like "if parameter binding fails and there are dynamic parameters, go back and assume unknown parameters are switch parameters and try again". This could be done one unknown parameter at a time, or all at once, either way, parameter binding could be really slow if there are many unknown parameters.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With