按位置传递函数参数:在管道输入之前是否使用显式值?

Passing function arguments by position: Do explicit values get used before pipeline input?

我正在尝试创建一个可以按位置接收多个参数的函数,包括管道输入。

这是一个简单的测试函数:

function TestMultiplePositionalParameters
{
    param
    (  
        [Parameter(
            Position=0, 
            Mandatory=$true)
        ]
        [String]$FirstParam,

        [Parameter(
            Position=1, 
            Mandatory=$true, 
            ValueFromPipeline=$true)
        ]
        [String]$SecondParam
    ) 

    begin
    {
        Write-Host '================================='
    }

    process
    {
        Write-Host '$FirstParam:' $FirstParam
        Write-Host '$SecondParam:' $SecondParam
        Write-Host ''        
    }
}

当我调用它时,它工作正常:

"Input1","Input2" | TestMultiplePositionalParameters 'ExplicitArgument'

这导致:

=================================
$FirstParam: ExplicitArgument
$SecondParam: Input1

$FirstParam: ExplicitArgument
$SecondParam: Input2

但是,如果我更改从管道获取值的参数:

function TestMultiplePositionalParameters
{
    param
    (  
        [Parameter(
            Position=0, 
            Mandatory=$true, 
            ValueFromPipeline=$true)
        ]
        [String]$FirstParam,

        [Parameter(
            Position=1, 
            Mandatory=$true)
        ]
        [String]$SecondParam
    ) 

    # etc...

}

再次调用它:

"Input1","Input2" | TestMultiplePositionalParameters 'ExplicitArgument'

这次报错:

TestMultiplePositionalParameters : The input object cannot be bound to any parameters 
for the command either because the command does not take pipeline input or the input 
and its properties do not match any of the parameters that take pipeline input.
At C:\...\DEMO_Function_Pipeline_MultiPositionalParams.ps1:77 char:21
+ "Input1","Input2" | TestMultiplePositionalParameters 'ExplicitArgument'
+                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (Input1:String) 
   [TestMultiplePositionalParameters ], ParameterBindingException
    + FullyQualifiedErrorId : InputObjectNotBound,TestMultiplePositionalParameters

我的问题是:为什么函数的第二个版本将显式参数 'ExplicitArgument' 传递给第一个参数?我本以为只有第一个参数可以接受管道输入,函数应该将管道输入传递给第一个参数,并将显式参数传递给第二个参数。

Why does the second version of the function pass the explicit argument 'ExplicitArgument' to the first parameter?

因为 $FirstParam 被标记为位置“0”并且传递给 cmdlet 的第一个参数是 'ExplicitArgument'。本质上,当 PowerShell 正在寻找将接受管道输入的参数时,'ExplicitArgument' 到 $FirstParam 的绑定已经发生。

要获得预期的行为,您必须执行以下操作:

"Input1","Input2" | TestMultiplePositionalParameters -SecondParam 'ExplicitArgument'

这样做的原因是您可以有多个参数从管道接受其值。如果您有以下内容,您希望在第二个示例中发生什么?

param
(  
    [Parameter(
        Position=0, 
        Mandatory=$true, 
        ValueFromPipeline=$true)
    ]
    [String]$FirstParam,

    [Parameter(
        Position=1, 
        Mandatory=$true,
        ValueFromPipeline=$true)
    ]
    [String]$SecondParam
) 

必须有一个优先级,命名和位置参数比管道参数具有更高的优先级。