Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic switches before positional parameters may not work as expected

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:

  • Is my understanding of the problem correct?
  • Is this feature documented somewhere?
  • Is there any workaround?

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

  • The described problem exists.
  • It is not documented as such.
  • Ways to work around, each solves the problem:
    • Specify dynamic switches after positional parameter arguments
    • Specify dynamic switch arguments explicitly: -ReadOnly:$true
    • Do not use positional parameters together with dynamic switches, i.e. specify parameter names.

Opened the bug: 960194

like image 785
Roman Kuzmin Avatar asked Aug 29 '14 00:08

Roman Kuzmin


People also ask

What are the positional parameters?

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.

What is a positional parameter in PowerShell?

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.

What is a switch parameter PowerShell?

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.


1 Answers

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.

like image 171
Jason Shirk Avatar answered Oct 26 '22 16:10

Jason Shirk