简体   繁体   English

位置绑定和参数集

[英]Postional Binding and ParameterSets

I'm struggling to understand the behavior of parameter sets and positional binding.我正在努力理解参数集和位置绑定的行为。 Here is the sample function.这是示例 function。

function Test-PositionBinding {
    [CmdletBinding(DefaultParameterSetName = 'ParamSet2')]
    param (
        [Parameter(ParameterSetName='ParamSet1',Position = 0)]
        [int]
        $param1,

        [Parameter(ParameterSetName='ParamSet1',Position = 1)]
        [int]
        $param2,

        [Parameter(ParameterSetName='ParamSet2',Position = 0)]
        [int]
        $param3
    )    
    process {
        $PSCmdlet.ParameterSetName
        $param1
        $param2
        $param3
    }
}

Based on the help output it would seem that calling the function with a single int should use paramset1 and calling it with 2 int should use paramset2 which is what i would expect.根据 output 的帮助,似乎用单个 int 调用 function 应该使用 paramset1,用 2 int 调用它应该使用 paramset2,这正是我所期望的。

SYNTAX
    Test-PositionBinding [[-param3] <int>] [<CommonParameters>]

    Test-PositionBinding [[-param1] <int>] [[-param2] <int>] [<CommonParameters>]

However, I receive the following output.但是,我收到以下 output。

PS C:\> Test-PositionBinding 1
ParamSet2
0
0
1
PS C:\> Test-PositionBinding 1 2

Test-PositionBinding: A positional parameter cannot be found that accepts argument '2'.

I would have expected the following.我会期待以下。

PS C:\> Test-PositionBinding 1 2
ParamSet1
1
2
0

If we change the type of param1 to a string the function works as expected.如果我们将 param1 的类型更改为字符串,则 function 将按预期工作。

PS C:\> Test-PositionBinding 1
ParamSet2

0
1
PS C:\> Test-PositionBinding 'abc'
ParamSet1
abc
0
0
PS C:\> Test-PositionBinding 'abc' 2
ParamSet1
abc
2
0

What is it that I am misunderstanding about the way PS interprets parameter sets?我对 PS 解释参数集的方式有什么误解?

Ultimately my question, is why is PS unable to differentiate between 2 parameter sets with positional binding and different parameter counts if the first parameter is of the same type between sets.最终我的问题是,如果第一个参数在集合之间的类型相同,为什么 PS 无法区分具有位置绑定和不同参数计数的 2 个参数集。

If you add an IF you can see when you choose param 1 or 2 you are in paramset 1如果添加 IF,您可以在选择参数 1 或 2 时看到您在参数集 1 中

if you choose param1 or 2 you can't select param 3 or 4如果你选择 param1 或 2 你不能 select 参数 3 或 4

if you run Test-postionbinding 1如果你运行 Test-postionbinding 1

Then since param1 is defined as 0 it will powershell will automatically bind the first parameter passed to the function to position 0.然后,由于 param1 被定义为 0,因此 powershell 将自动将传递给 function 的第一个参数绑定到 position 0。
if you pass 0 -param4 1如果你通过 0 -param4 1
Param3 will have a value of 0 and param4 will be 1 and you fall into paramset2. Param3 的值为 0,param4 为 1,您将进入 paramset2。

If you specify param1 then your only other parameter is param2 because its a member of Paramset1如果您指定 param1,那么您唯一的其他参数是 param2,因为它是 Paramset1 的成员

If you choose param3 then the only other available param is param4 because it's part of paramset2如果您选择 param3,那么唯一可用的其他参数是 param4,因为它是 paramset2 的一部分

function Test-PositionBinding {
    [CmdletBinding(DefaultParameterSetName = 'ParamSet2')]
    param (
        [Parameter(ParameterSetName='ParamSet1',Position = 0)]
        [int]
        $param1,

        [Parameter(ParameterSetName='ParamSet1',Position = 1)]
        [int]
        $param2,

        [Parameter(ParameterSetName='ParamSet2',Position = 0)]
        [int]
        $param3
    )    
    process {
        if($PSCmdlet.ParameterSetName -eq "paramset1")
        {
            write-output "Paramset1"
            $param1
            $param2
        }

        if($PSCmdlet.ParameterSetName -eq "paramset2")
        {
            write-output "Paramset2"
            $param3
            $param4
        }
    }
}

Observing position 2 binding观察 position 2 绑定

Test-PositionBinding -param1 1 10
Paramset1
1
10

Observing paramset2观察参数集2

Test-PositionBinding -param3 10
Paramset2
10

using no parameter names and forcing powershell to use the binding specified: Test-PositionBinding 0 1 Test-PositionBinding: A position不使用参数名称并强制 powershell 使用指定的绑定:Test-PositionBinding 0 1 Test-PositionBinding:A position

al parameter cannot be found that accepts argument '1'.
At line:1 char:1
+ Test-PositionBinding 0 1
+ ~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Test-PositionBinding], ParameterBindingException
    + FullyQualifiedErrorId : PositionalParameterNotFound,Test-PositionBinding


PS C:\WINDOWS\system32> Test-PositionBinding 0
Paramset2
0

As per the MS Docs: 根据 MS Docs:

Parameter set requirements The following requirements apply to all parameter sets.参数集要求 以下要求适用于所有参数集。

Each parameter set must have at least one unique parameter.每个参数集必须至少有一个唯一参数。 If possible, make this parameter a mandatory parameter.如果可能,请将此参数设置为强制参数。

A parameter set that contains multiple positional parameters must define unique positions for each parameter.包含多个位置参数的参数集必须为每个参数定义唯一的位置。 No two positional parameters can specify the same position.没有两个位置参数可以指定相同的 position。

Only one parameter in a set can declare the ValueFromPipeline keyword with a value of true.一组参数中只有一个参数可以声明 ValueFromPipeline 关键字的值为 true。 Multiple parameters can define the ValueFromPipelineByPropertyName keyword with a value of true.多个参数可以定义值为 true 的 ValueFromPipelineByPropertyName 关键字。

If no parameter set is specified for a parameter, the parameter belongs to all parameter sets.如果没有为参数指定参数集,则该参数属于所有参数集。

This is a good write up on this topic that kept around that helped me.这是一篇关于这个主题的好文章,对我有帮助。 Snipping it here, vs just giving you the link to bounce over to.在这里剪掉它,而不是只给你一个跳转到的链接。 Thogh this is not parameterset specific, the same rules apply.尽管这不是特定于参数集的,但适用相同的规则。

Specifying PowerShell Parameter Position 指定 PowerShell 参数 Position

It makes sense for some commands to allow you to pass things by position rather than by name, especially in cases where there would be little confusion if the names of the parameters are left out (as in this example).对于某些命令来说,允许您通过 position 而不是通过名称传递内容是有意义的,尤其是在省略参数名称(如本例中)的情况下,会造成一些混乱。

function Test-Position
{
    [CmdletBinding()]
    Param
    (
        [parameter(Position=0)]$parm1,
        [parameter(Position=1)]$parm2,
        [parameter(Position=2)]$parm3,
        [parameter(Position=3)]$parm4
    )
}

What should I do?我应该怎么办?

> According to the help (about_Functions_CmdletBindingAttribute), you should use the PositionalBinding optional argument to the CmdletBinding() attribute, and set it to $false. > 根据帮助(about_Functions_CmdletBindingAttribute),您应该使用 CmdletBinding() 属性的 PositionalBinding 可选参数,并将其设置为 $false。

That will cause all parameters to default to not be allowed by position.这将导致 position 不允许所有参数默认。 Then, > you can specify the Position for any (hopefully only one or two) parameters you wish to be used by position.然后,> 您可以为您希望 position 使用的任何(希望只有一两个)参数指定 Position。

For instance, this will only allow $parm1 to be used by position:例如,这将只允许 position 使用 $parm1:

function Test-Position
{
    [CmdletBinding(PositionalBinding = $false)]
    Param([parameter(Position=0)]$parm1,
                                    $parm2,
                                    $parm3,
                                    $parm4)
}

But wait, it gets easier但是等等,它变得更容易了

Even though the help says that all parameters are positional by default, it turns out that using Position on one parameter means that you have to use it on any parameters you want to be accessed by position.尽管帮助说明默认情况下所有参数都是位置参数,但事实证明,在一个参数上使用 Position 意味着您必须在 position 访问的任何参数上使用它。

For instance, in this version of the function I haven't specified ositionalBinding=$False in the CmdletBinding attribute, but only the first parameter is available by position.例如,在这个版本的 function 中,我没有在 CmdletBinding 属性中指定 ositionalBinding=$False,但 position 只能使用第一个参数。

function Test-Position2
{
    [CmdletBinding()]
    Param
    (
        [parameter(Position=0)]$parm1, 
                                $parm2, 
                                $parm3, 
                                $parm4
    )
}

That's interesting to me, as it seems to contradict what's in the help.这对我来说很有趣,因为它似乎与帮助中的内容相矛盾。 Specifically, the help says that all parameters are positional.具体来说,帮助说所有参数都是位置的。 It then says that in order to disable this default, you should use the PositionalBinding parameter.然后它说为了禁用这个默认值,你应该使用 PositionalBinding 参数。 This shows that you don't need to do that, unless you don't want any positional parameters.这表明您不需要这样做,除非您不想要任何位置参数。

As a final example, just to make sure we understand how the Position value is used, consider the following function and syntax help:作为最后一个示例,为了确保我们了解如何使用 Position 值,请考虑以下 function 和语法帮助:

function Test-Position3
{
    [CmdletBinding()]
    Param
    (
        $parm1,
        $parm2,
        [parameter(Position=1)]$parm3,
        [parameter(Position=0)]$parm4
    )
}

By including Position on 2 of the parameters, we've ensured that the other two parameters are only available by name.通过在其中两个参数中包含 Position,我们确保了其他两个参数只能通过名称获得。 Also, the assigned positions differ from the order that the parameters are defined in the function, and that is reflected in the syntax help.此外,分配的位置与 function 中定义的参数顺序不同,这反映在语法帮助中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM