powershellbindingoperator-precedence

What is the precedence of parameter binding?


I am a PowerShell novice. Suppose that I wish to call

Get-Service -Name winrm, netlogon

Due to parameter binding, this will be parsed as if we typed @("winrm", "netlogon") rather than winrm, netlogon. But what is the precedence of parameter binding? Can anything happen before it? The documentation lists the comma operator as having very high precedence. But, somehow, parameter binding beats it.


Solution


  • Given that argument winrm, netlogon is passed to a PowerShell command, it is indeed equivalent to the following expression: @('winrm', 'netlogon'), i.e. it constructs a 2-element array whose elements are strings.[1]

    By contrast, an external program would see this as two arguments, namely verbatim winrm, and netlogon.[2]

    If you want any given command to receive winrm, netlogon as a single string, use quoting, e.g. a verbatim string, '...', i.e. 'winrm, netlogon'; if you need string interpolation (expansion), use an expandable string, "...", e.g. "$serviceName1, netlogon"

    If you want to use , verbatim as part of a bareword, use `, the so-called backtick, PowerShell's escape character, e.g. winrm`,

    For a comprehensive overview of how unquoted command arguments are parsed in argument mode, see this answer.


    [1] But note that it depends on the type of the parameter of the target command that the argument binds whether an array is accepted as such. See this answer for more information.

    [2] This applies to PowerShell (Core) 7; in Windows PowerShell (the legacy, ships-with-Windows, Windows-only edition of PowerShell whose latest and last version is 5.1), the trailing , is _stripped from winrm. By contrast, if you were to pass winrm,netlogin, i.e. a token without spaces, verbatim winrm,netlogin would be passed in both editions. Another notably difference - which is regrettable owed to a bug - is that PowerShell (Core) 7 neglects to expand (interpolate) the ,-separated elements when calling external programs, even though it should, and does so both in isolation and when calling PowerShell commands; e.g., passing $HOME alone to an external program passes the value of said variable in both editions, but passing $HOME, foo does not result in expansion of $HOME in PowerShell 7 as of v7.5.x. See GitHub issue #18502 for the relevant bug report.