powershell cmdlet:位置vs.管道是他们互相攻击?

时间:2013-03-05 21:39:35

标签: powershell cmdlets cmdlet

我的cmdlet尝试获取2个参数,1来自管道,1来自用户输入,我想知道是否可以通过位置参数来完成它,就像这样:

Set-login name pw | add-view viewName

其中add-view就像:

[parameter(position=0, ValueFromPipeline = true, ValueFromPipelineByPropertyName = true, Mandatory = true)]
public loginInfo Login {}
[parameter(position=1, Mandatory = true)]
public String Name {}
...

但是,有了上述属性,

Set-login name pw | add-view viewName 

会返回错误,指出无法将String转换为loginInfo,我必须这样做:

$a = Set-login name pw
Add-View $a viewnames

$a | Add-View -Name viewnames

看来位置参数和管道是相互对立的,这是真的吗?工作是什么?

谢谢!

1 个答案:

答案 0 :(得分:3)

解决方案:将Name参数移动到第一个位置,以确保传递的字符串将绑定到此参数而不是Login参数,即要将值传递给使用管道的参数。< / p>

原因:内联参数绑定是在管道处理开始之前发生的一个过程。例如,简单函数,有点类似于您的cmdlet:

function Test-FooBar {
param (
    [Parameter(ValueFromPipeline)]
    $Foo,
    $Bar
)

process {
    "Foo: $Foo Bar: $Bar"
}
}

取决于位置绑定(使用从第一个位置的管道获取值的位置绑定):

Trace-Command -Name ParameterBinding -Expression { 1 | Test-FooBar 2} -PSHost
DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Foo-Bar]
DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Foo-Bar]
DEBUG: ParameterBinding Information: 0 :     BIND arg [2] to parameter [Foo]
DEBUG: ParameterBinding Information: 0 :         BIND arg [2] to param [Foo] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Foo-Bar]
DEBUG: ParameterBinding Information: 0 :     BIND arg [] to parameter [Bar]
DEBUG: ParameterBinding Information: 0 :         BIND arg [] to param [Bar] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
(...)

'2'已绑定到第一个位置,因此您将收到管道输入无法绑定(最终)的错误。

同样,但这次我们确保'2'将被绑定到第二个参数:

Trace-Command -Name ParameterBinding -Expression { 1 | Test-FooBar -Bar 2} -PSHost
DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Test-FooBar]
DEBUG: ParameterBinding Information: 0 :     BIND arg [2] to parameter [Bar]
DEBUG: ParameterBinding Information: 0 :         COERCE arg to [System.Object]
DEBUG: ParameterBinding Information: 0 :             Parameter and arg types the same, no coercion is needed.
DEBUG: ParameterBinding Information: 0 :         BIND arg [2] to param [Bar] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Test-FooBar]
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Test-FooBar]
DEBUG: ParameterBinding Information: 0 :     BIND arg [] to parameter [Foo]
DEBUG: ParameterBinding Information: 0 :         BIND arg [] to param [Foo] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : BIND PIPELINE object to parameters: [Test-FooBar]
DEBUG: ParameterBinding Information: 0 :     PIPELINE object TYPE = [System.Int32]
DEBUG: ParameterBinding Information: 0 :     RESTORING pipeline parameter's original values
DEBUG: ParameterBinding Information: 0 :     Parameter [Foo] PIPELINE INPUT ValueFromPipeline NO COERCION
DEBUG: ParameterBinding Information: 0 :     BIND arg [1] to parameter [Foo]
DEBUG: ParameterBinding Information: 0 :         BIND arg [1] to param [Foo] SUCCESSFUL
(...)

正如您现在所看到的 - 一旦BeginProcessing被称为BIND PIPELINE触发器,并且因为仍然存在接受管道输入的参数 - 它工作正常。