因此,我正在尝试使用PowerShell,并且在理解参数时遇到了一些麻烦。从我所阅读的内容来看,如果我将一个参数指定为与另一个参数相同的位置,但是将其放置在单独的ParameterSet中,那么PowerShell仅需要存在这些参数之一。
在此示例中,按预期工作-
[CmdletBinding(DefaultParameterSetName='MultiUser')]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$Token,
[Parameter(Mandatory=$True,Position=2, ParameterSetName="MultiUser")]
[string]$UsernamesFile,
[Parameter(Mandatory=$True,Position=2, ParameterSetName="SingleUser")]
[string]$SingleUsername,
[Parameter(Mandatory=$False)]
[switch]$SpecialCase
)
但是,如果我想对此进行扩展,以便如上所述,您必须指定一个 token ,然后必须指定一个用户名文件或一个用户名文件,但是现在我想指定一个用户所属的组。
现在让我们假设用户必须进入两个组之一,而我不想担心以不同的方式处理用户可能输入的组名,因此我使用两个开关。我只希望用户位于一个组中,而不是两个组中,因此开关应位于相同的位置,但应位于不同的参数集中(基于我所读的内容以及以上示例的工作原理)。
所以我的第二个例子看起来像这样-
[CmdletBinding(DefaultParameterSetName='MultiUser')]
Param(
[Parameter(Mandatory=$True,Position=1)]
[string]$Token,
[Parameter(Mandatory=$True,Position=2, ParameterSetName="MultiUser")]
[string]$UsernamesFile,
[Parameter(Mandatory=$True,Position=2, ParameterSetName="SingleUser")]
[string]$SingleUsername,
[Parameter(Mandatory=$True,Position=3, ParameterSetName="GroupA")]
[switch]$GroupA,
[Parameter(Mandatory=$True,Position=3, ParameterSetName="GroupB")]
[switch]$GroupB,
[Parameter(Mandatory=$False)]
[switch]$SpecialCase
)
这不能按预期工作,但是,这给了我一个错误-
有人可以解释为什么这行不通并更正我对PowerShell参数的理解吗?
谢谢!
最佳答案
请参阅底部以获取关于OP的方法问题的解释。
要准确获得您所要求的,您必须使用以下内容:
# - Make sure that parameters are NON-positional unless explicitly marked otherwise.
# - Specify the default parameter set.
[CmdletBinding(PositionalBinding=$False, DefaultParameterSetName='MultiUserA')]
Param(
# Belongs to all parameter sets.
[Parameter(Mandatory, Position=1)]
[string]$Token,
# Mandatory and positional both when combined with -GroupA or -GroupB.
[Parameter(Mandatory, Position=2, ParameterSetName='MultiUserA')]
[Parameter(Mandatory, Position=2, ParameterSetName='MultiUserB')]
[string] $UsernamesFile,
# Mandatory - but not positional - both when combined with -GroupA or -GroupB.
[Parameter(Mandatory, ParameterSetName='SingleUserA')]
[Parameter(Mandatory, ParameterSetName='SingleUserB')]
[string] $SingleUsername,
# Mandatory, whether combined with -UsernamesFile or -SingleUsername
[Parameter(Mandatory, ParameterSetName='SingleUserA')]
[Parameter(Mandatory, ParameterSetName='MultiUserA')]
[switch] $GroupA,
# Mandatory, whether combined with -UsernamesFile or -SingleUsername
[Parameter(Mandatory, ParameterSetName='SingleUserB')]
[Parameter(Mandatory, ParameterSetName='MultiUserB')]
[switch] $GroupB,
# Belongs to all parameter sets. Non-mandatory by default.
[switch] $SpecialCase
)
如你看到的,
[Parameter(...)]
属性只能指定1个参数集,在此指定的任何其他属性Mandatory
,Position
,...-仅在给定参数集的上下文中适用于该参数。 当您使用
-?
调用脚本(或将其传递给Get-Help
)时,您将看到生成的语法图:script.ps1 [-Token] <string> [-UsernamesFile] <string> -GroupA [-SpecialCase] [<CommonParameters>]
script.ps1 [-Token] <string> [-UsernamesFile] <string> -GroupB [-SpecialCase] [<CommonParameters>]
script.ps1 [-Token] <string> -SingleUsername <string> -GroupB [-SpecialCase] [<CommonParameters>]
script.ps1 [-Token] <string> -SingleUsername <string> -GroupA [-SpecialCase] [<CommonParameters>]
但是,由于以下原因,这种方法是不明智的:
[switch]
参数,因为根据定义它们是可选的。 true
,false
,1
,0
,...-尝试使用./script someToken someFile
)./script.ps1 someToken -SingleUsername someUser
提供一般错误消息(Parameter set cannot be resolved using the specified named parameters.
),而不是专门指出缺少-GroupA
或-GroupB
,因为PowerShell无法知道您是指参数集SingleUserA
还是SingleUserB
。./script someToken someFile
(带有隐含的-UsernamesFile
)是明确的,因为MultiUserA
是默认参数集,但是由于-GroupA
开关是强制性的,因此仍然会提示您输入其值。 -GroupA
与-GroupB
)不能很好地扩展,因为快速添加更多的-Group*
开关会使必须分别反射(reflect)在自己参数中的组合数量设置难以管理-请参阅下文了解如何避免这种情况。 如Mathias R. Jessen's helpful answer所指出的,更好的方法是对目标组使用单个参数,即仅接受给定值中的值,
[ValidationAttribute]
可以确保:[CmdletBinding(PositionalBinding=$False, DefaultParameterSetName='MultiUser')]
Param(
[Parameter(Mandatory, Position=1)]
[string] $Token,
[Parameter(Mandatory, Position=2, ParameterSetName='MultiUser')]
[string] $UsernamesFile,
[Parameter(Mandatory, ParameterSetName='SingleUser')]
[string] $SingleUsername,
# Single -Group parameter that only accepts values 'GroupA' and 'GroupB'
# Input validation is case-INsensitive, as usual.
[Parameter(Mandatory)]
[ValidateSet('GroupA', 'GroupB')]
[string] $Group,
[switch] $SpecialCase
)
这为我们提供了以下语法图(请注意,未反射(reflect)
-Group
的有效值集):script.ps1 [-Token] <string> [-UsernamesFile] <string> -Group <string> [-SpecialCase] [<CommonParameters>]
script.ps1 [-Token] <string> -SingleUsername <string> -Group <string> [-SpecialCase] [<CommonParameters>]
-Group
,那么./script.ps someToken someFile
和./script.ps someToken -SingleUserName someUser
现在的行为相同:它们提示输入-Group
值。 -Group
,并且调用值比使用不同的开关-GroupA
和-GroupB
稍微麻烦一些,至于您的原始方法的问题:
./script.ps1 -Token a -UsernamesFile someFile -GroupA
的尝试失败,因为:-GroupA
仅属于参数集GroupA
,而-UsersnameFile
仅属于参数集MultiUser
,因此这些参数实际上是互斥的,PowerShell无法确定要使用的参数集。 [CmdletBinding(PositionalBinding=$False,...)]
显式停用它,否则只有显式标记为[Parameter(...)]
属性的各个Position
属性才变为位置参数。 [switch]
参数设置为无位置是没有意义的,因为根据定义它们是非位置的:您必须始终(明确地)指定其名称,并且可以将它们放置在任何位置。 关于powershell - 参数-需要一些而不是其他-正确使用参数集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43018188/