如何解决管道参数与其他参数的特定组合时“无法解析参数集”
我编写了一个使用四个参数和四个参数集的函数。第一个参数 $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,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
,因为它的两个集合都使用了完全必需参数的不同组合。当同时使用 $Path
和 $OutputMode
时会出现集合 B,仅此而已。那么,"C:\Test.jpg" | Foo-Bar -OutputMode 1
是如何被认为是模棱两可的?
我将非常感谢任何可以为我阐明这一点的人。
解决方法
不要问我为什么。
(以下解决方法返回相同的语法:Foo-Bar -?
)
就我个人而言,我发现参数集安静混乱且冗长(因此我为 Hierarchical Parameter Scripting #13746
做了这个目的)
无论如何,作为一种可能的解决方法;将 Path
参数放入所有参数集中:
function Foo-Bar {
[CmdletBinding(DefaultParameterSetName = 'A')]
param (
[Parameter(Mandatory = $true,ValueFromPipeline = $true,ParameterSetName = 'A')]
[Parameter(Mandatory = $true,ParameterSetName = 'B')]
[Parameter(Mandatory = $true,ParameterSetName = 'A-Secure')]
[Parameter(Mandatory = $true,ParameterSetName = 'B-Secure')]
[ValidateNotNullOrEmpty()]
[string[]] $Path,[Parameter(ParameterSetName = 'A')]
[Parameter(ParameterSetName = 'A-Secure')]
[Switch] $OutputToConsole,[Parameter(Mandatory = $true,ParameterSetName = 'B-Secure')]
[int] $OutputMode,ParameterSetName = 'B-Secure')]
[Switch] $Login
)
$PSCmdlet.ParameterSetName
}
"C:\Test.jpg" | Foo-Bar -Login
A-Secure
,
参数集必须至少包含一个唯一参数
声明参数集要创建参数集,您必须指定 每个参数的 Parameter 属性的 ParameterSetName 关键字 参数集中的参数。对于属于多个的参数 参数集,为每个参数集添加一个 Parameter 属性。
Parameter 属性使您能够定义参数 每个参数集不同。例如,您可以定义一个 参数在一组中是必需的,在另一组中是可选的。 不过, 每个参数集必须至少包含一个唯一参数。
没有指定参数集名称的参数属于 所有参数集。
更新 - 仔细观察
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-Secure 中您有一个额外的强制性参数 (-OutputMode
) 并不重要。从它收到的信息来看,它无法判断要使用哪个,因为有多个匹配选项。这种组合不是唯一的。
"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。
遵循iRons answer,我认为您还可以在这里大幅减少参数集的数量:
function Foo-Bar {
[CmdletBinding(DefaultParameterSetName = 'None')]
param (
[ValidateNotNullOrEmpty()]
[string[]] $Path,[Parameter(ParameterSetName = 'A-Secure')]
[Switch] $OutputToConsole,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'
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。