2

我编写了一个使用四个参数和四个参数集的函数。第一个参数$Path未分配给集合,因此属于所有集合。它也是强制性的,并且是唯一可以从管道传递的参数。但是,当我在管道末尾调用函数时使用其他三个参数的某些组合(所有这些参数都属于四组的某种组合)执行此操作时,我收到一个错误,表明该组不明确。

这是我的功能:

function Foo-Bar {
    [CmdletBinding(DefaultParameterSetName = 'A')]

    param (
        [Parameter(Mandatory = $true,
            ValueFromPipeline = $true)]
        [ValidateNotNullOrEmpty()]
        [string[]] $Path,

        [Parameter(ParameterSetName = 'A')]
        [Parameter(ParameterSetName = 'A-Secure')]
        [Switch] $OutputToConsole,

        [Parameter(Mandatory = $true,
            ParameterSetName = 'B')]
        [Parameter(Mandatory = $true,
            ParameterSetName = 'B-Secure')]
        [int] $OutputMode,

        [Parameter(Mandatory = $true,
            ParameterSetName = 'A-Secure')]
        [Parameter(Mandatory = $true,
            ParameterSetName = 'B-Secure')]
        [Switch] $Login
    )

    $PSCmdlet.ParameterSetName
}

所有可能的参数组合如下:

PS C:\> Foo-Bar -Path "C:\Test.jpg"
A
PS C:\> Foo-Bar -Path "C:\Test.jpg" -OutputToConsole
A
PS C:\> Foo-Bar -Path "C:\Test.jpg" -OutputToConsole -Login
A-Secure
PS C:\> Foo-Bar -Path "C:\Test.jpg" -Login
A-Secure
PS C:\> Foo-Bar -Path "C:\Test.jpg" -OutputMode 1
B
PS C:\> Foo-Bar -Path "C:\Test.jpg" -OutputMode 1 -Login
B-Secure

单独通过管道传递 $Path ,或与这些其他参数组合一起工作正常:

PS C:\> "C:\Test.jpg" | Foo-Bar
A
PS C:\> "C:\Test.jpg" | Foo-Bar -OutputToConsole
A
PS C:\> "C:\Test.jpg" | Foo-Bar -OutputToConsole -Login
A-Secure
PS C:\> "C:\Test.jpg" | Foo-Bar -OutputMode 1 -Login
B-Secure

但是这两种组合会导致错误:

PS C:\> "C:\Test.jpg" | Foo-Bar -Login
Foo-Bar: Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be used together or an insufficient number of parameters were provided.
PS C:\> "C:\Test.jpg" | Foo-Bar -OutputMode 1
Foo-Bar: Parameter set cannot be resolved using the specified named parameters. One or more parameters issued cannot be used together or an insufficient number of parameters were provided.

这些结果之间的最大区别似乎是$OutputToConsole,这是两个集合中唯一可选的参数。似乎管道强制参数会导致它本身成为强制参数。另一方面,最令人困惑的结果涉及$OutputMode,因为它的两个集合都使用完全强制参数的不同组合。Set B 在同时使用$Pathand时发生$OutputMode,仅此而已。那么它是如何"C:\Test.jpg" | Foo-Bar -OutputMode 1被认为是模棱两可的呢?

我将非常感谢任何可以为我阐明这一点的人。

4

3 回答 3

4

不要问我为什么
(下面的解决方法返回相同的语法:)就Foo-Bar -?个人
而言,我发现参数集非常混乱和冗长(因此我为分层参数脚本#13746做了这个目的)

无论如何,作为一种可能的解决方法;将Path参数放入所有参数集中:

function Foo-Bar {
    [CmdletBinding(DefaultParameterSetName = 'A')]

    param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'A')]
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'B')]
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'A-Secure')]
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'B-Secure')]
        [ValidateNotNullOrEmpty()]
        [string[]] $Path,

        [Parameter(ParameterSetName = 'A')]
        [Parameter(ParameterSetName = 'A-Secure')]
        [Switch] $OutputToConsole,

        [Parameter(Mandatory = $true, ParameterSetName = 'B')]
        [Parameter(Mandatory = $true, ParameterSetName = 'B-Secure')]
        [int] $OutputMode,

        [Parameter(Mandatory = $true, ParameterSetName = 'A-Secure')]
        [Parameter(Mandatory = $true, ParameterSetName = 'B-Secure')]
        [Switch] $Login
    )

    $PSCmdlet.ParameterSetName
}

"C:\Test.jpg" | Foo-Bar -Login
A-Secure
于 2021-05-27T07:26:48.833 回答
1

参数集必须至少包含一个唯一参数

声明参数集 要创建参数集,您必须为参数集中的每个参数指定 Parameter 属性的 ParameterSetName 关键字。对于属于多个参数集的参数,为每个参数集添加一个 Parameter 属性。

Parameter 属性使您能够为每个参数集定义不同的参数。例如,您可以将一个参数定义为一组中的必需参数和另一组中的可选参数。但是,每个参数集必须至少包含一个唯一参数。

没有指定参数集名称的参数属于所有参数集。

来源:声明参数集


更新 - 仔细看看

美食吧

ParameterSetName Parameters
---------------- ----------
A                -Path <string[]> [-OutputToConsole] [<CommonParameters>]
A-Secure         -Path <string[]> -Login [-OutputToConsole] [<CommonParameters>]
B-Secure         -Path <string[]> -OutputMode <int> -Login [<CommonParameters>]
B                -Path <string[]> -OutputMode <int> [<CommonParameters>]

当你进入

C:\Test.jpg" | Foo-Bar -Login

PoSH 无法确定它应该使用 A-Secure 还是 B-Secure。-OutputMode在 B-Secure 中您有一个额外的强制参数 ( )并不重要。从它收到的内容来看,它无法判断要选择哪个,因为有多种匹配选择。这种组合并不是唯一的。

"C:\Test.jpg" | Foo-Bar -OutputMode 1

与此处相同,仅输出模式。它收到了一个 Path 和一个 OutputMode 参数,但它同时匹配 B-Secure 和 B。不是唯一的。

Microsoft Measure-Lines 示例

ParameterSetName Parameters
---------------- ----------
Path             [-Path] <string[]> [-Lines] [-Words] [-Characters] [-Recurse] [<CommonParameters>]
PathAll          [-Path] <string[]> -All [-Recurse] [<CommonParameters>]
LiteralPath      -LiteralPath <string> [-Lines] [-Words] [-Characters] [<CommonParameters>]
LiteralPathAll   -LiteralPath <string> -All [<CommonParameters>]

乍一看,Measure-Lines 示例似乎相似,但不同之处在于前 2 个参数集采用 Path 参数,而后 2 个参数集采用 LiteralPath 参数。这使得它们足够独特,以便 Powershell 知道在例如使用-All开关时使用什么参数集。当与-Path参数一起使用时,它与 PathAll 集一起使用,并且在-LiteralPath提供时使用 LiteralPathAll。

于 2021-05-27T05:10:11.723 回答
0

iRons 回答之后,我认为您还可以在这里大幅减少参数集的数量:

function Foo-Bar {
    [CmdletBinding(DefaultParameterSetName = 'None')]

    param (
        [ValidateNotNullOrEmpty()]
        [string[]] $Path,

        [Parameter(ParameterSetName = 'A-Secure')]
        [Switch] $OutputToConsole,

        [Parameter(Mandatory = $true, ParameterSetName = 'B-Secure')]
        [int] $OutputMode,

        [Parameter(Mandatory = $true, ParameterSetName = 'A-Secure')]
        [Parameter(Mandatory = $true, ParameterSetName = 'B-Secure')]
        [Switch] $Login
    )

    $PSCmdlet.ParameterSetName
}

Foo-Bar -Login                                            # --> chosen param set: 'A-Secure' because that the first one mentioned on the Login parameter
Foo-Bar -Path 'D:\Test\blah.txt'                          # --> chosen param set: 'None' because that is the DefaultParameterSetName
Foo-Bar -Path 'D:\Test\blah.txt' -OutputMode 5            # --> prompts you to also supply parameter 'Login'
Foo-Bar -Path 'D:\Test\blah.txt' -OutputToConsole -Login  # --> parameter -OutputMode now not available; chosen param set: 'B-Secure'
Foo-Bar -Path 'D:\Test\blah.txt' -OutputMode 5 -Login     # --> parameter -OutputToConsole now not available; chosen param set: 'A-Secure'

# parameters '-Path' and '-Login' are always available for both 'A-Secure' and 'B-Secure'
于 2021-05-27T13:24:55.090 回答