1

我正在努力理解参数集和位置绑定的行为。这是示例函数。

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
    }
}

根据帮助输出,似乎用单个 int 调用函数应该使用 paramset1,用 2 int 调用它应该使用 paramset2,这是我所期望的。

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

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

但是,我收到以下输出。

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'.

我会期待以下。

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

如果我们将 param1 的类型更改为字符串,则函数按预期工作。

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

我对 PS 解释参数集的方式有什么误解?

最终我的问题是,如果第一个参数在集合之间的类型相同,为什么 PS 无法区分具有位置绑定和不同参数计数的 2 个参数集。

4

2 回答 2

1

根据 MS Docs:

参数集要求 以下要求适用于所有参数集。

每个参数集必须至少有一个唯一参数。如果可能,请将此参数设置为强制参数。

包含多个位置参数的参数集必须为每个参数定义唯一的位置。没有两个位置参数可以指定相同的位置。

一组参数中只有一个参数可以声明 ValueFromPipeline 关键字的值为 true。多个参数可以定义值为 true 的 ValueFromPipelineByPropertyName 关键字。

如果没有为参数指定参数集,则该参数属于所有参数集。

这是一篇关于这个主题的好文章,对我有帮助。在这里剪掉它,而不是只给你一个跳转到的链接。尽管这不是特定于参数集的,但适用相同的规则。

指定 PowerShell 参数位置

某些命令允许您按位置而不是按名称传递内容是有意义的,尤其是在省略参数名称(如本例中)时几乎不会混淆的情况下。

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

我应该怎么办?

> 根据帮助(about_Functions_CmdletBindingAttribute),您应该使用 CmdletBinding() 属性的 PositionalBinding 可选参数,并将其设置为 $false。

这将导致所有参数默认为不允许位置。然后, > 您可以为您希望位置使用的任何(希望只有一两个)参数指定位置。

例如,这将只允许 $parm1 被位置使用:

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

但是等等,它变得更容易了

尽管帮助说明默认情况下所有参数都是位置参数,但事实证明,在一个参数上使用 Position 意味着您必须在要按位置访问的任何参数上使用它。

例如,在这个版本的函数中,我没有在 CmdletBinding 属性中指定 ositionalBinding=$False,但只有第一个参数可以按位置使用。

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

这对我来说很有趣,因为它似乎与帮助中的内容相矛盾。具体来说,帮助说所有参数都是位置的。然后它说为了禁用这个默认值,你应该使用 PositionalBinding 参数。这表明您不需要这样做,除非您不想要任何位置参数。

作为最后一个示例,为了确保我们了解如何使用 Position 值,请考虑以下函数和语法帮助:

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

通过在 2 个参数上包含 Position,我们确保了其他两个参数只能通过名称使用。此外,分配的位置与函数中定义参数的顺序不同,这反映在语法帮助中。

于 2020-04-19T03:11:01.090 回答
0

如果添加 IF,您可以在选择参数 1 或 2 时看到您在参数集 1 中

如果你选择 param1 或 2 你不能选择 param 3 或 4

如果你运行 Test-postionbinding 1

然后,由于 param1 被定义为 0,powershell 将自动将传递给函数的第一个参数绑定到位置 0。
如果传递 0 -param4 1
Param3 的值为 0,param4 为 1,您将进入 paramset2。

如果您指定 param1,那么您唯一的其他参数是 param2,因为它是 Paramset1 的成员

如果您选择 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
        }
    }
}

观察位置 2 绑定

Test-PositionBinding -param1 1 10
Paramset1
1
10

观察参数集2

Test-PositionBinding -param3 10
Paramset2
10

不使用参数名称并强制 powershell 使用指定的绑定:Test-PositionBinding 0 1 Test-PositionBinding:一个位置

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
于 2020-04-17T03:02:12.483 回答