"Parameter set cannot be resolved" 使用其他参数的特定组合管道处理参数时



我编写了一个函数,它使用四个参数和四个参数集。第一个参数$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,因为它的两个集合都使用了完全强制性参数的不同组合。集合B发生在同时使用$Path$OutputMode的情况下,仅此而已。那么"C:Test.jpg" | Foo-Bar -OutputMode 1怎么会被认为是不明确的呢?

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

不要问我为什么
(下面的解决方法返回与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

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

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

使用"参数"属性可以定义参数对于每个参数集不同。例如,您可以定义参数在一个集合中是强制性的,在另一个集合则是可选的然而,每个参数集必须至少包含一个唯一的参数

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

来源:声明参数设置


更新-仔细查看

Foo Bar

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。在B安全中,您有一个额外的强制参数(-OutputMode(并不重要。根据它收到的信息,它无法判断该选择哪一个,因为有多种匹配的选择。这种组合并非独一无二。

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

这里也一样,只有OutputMode。它收到了一个Path和一个OutputMode参数,但这与B-Secure和B.都匹配。不是唯一的。

Microsoft测量线示例

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示例似乎相似,但不同之处在于前两个参数集采用Path参数,而后两个参数集中采用LiteralPath参数。这使得它们足够独特,Powershell可以知道在使用-All开关时要使用什么参数集。当与-Path参数一起使用时,它与PathAll集合一起使用,当提供-LiteralPath时使用LiteralPathAll。

根据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:Testblah.txt'                          # --> chosen param set: 'None' because that is the DefaultParameterSetName
Foo-Bar -Path 'D:Testblah.txt' -OutputMode 5            # --> prompts you to also supply parameter 'Login'
Foo-Bar -Path 'D:Testblah.txt' -OutputToConsole -Login  # --> parameter -OutputMode now not available; chosen param set: 'B-Secure'
Foo-Bar -Path 'D:Testblah.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'

最新更新