我有一个PowerShell函数,它接受一个字符串和三个开关。所以调用将是这样的:
My-Function "some string" -Switch1 -Switch2 -Switch3
但是,我想只在提供字符串和至少一个开关时才运行此功能。所以:
My-Function "some string" -Switch1 -Switch3 # Valid
My-Function "some string" -Switch2 # Valid
My-Function "some string" # Invalid
我知道我可以通过检查是否已使用$MyInvocation
对象传递开关来实现此目的,但有没有办法使用Parameter
和ParameterSet
属性执行此操作?
简而言之,这就是我想要做的事情:
答案 0 :(得分:3)
我认为您无法使用参数集和必需参数执行此操作。如果您使用交替的强制参数定义了3个不同的参数集,如下所示:
Param(
[Parameter(Mandatory=$true)]
[string]$Text,
[Parameter(Mandatory=$true, ParameterSetName='o1')]
[Parameter(Mandatory=$false, ParameterSetName='o2')]
[Parameter(Mandatory=$false, ParameterSetName='o3')]
[Switch][bool]$Switch1,
[Parameter(Mandatory=$false, ParameterSetName='o1')]
[Parameter(Mandatory=$true, ParameterSetName='o2')]
[Parameter(Mandatory=$false, ParameterSetName='o3')]
[Switch][bool]$Switch2,
[Parameter(Mandatory=$false, ParameterSetName='o1')]
[Parameter(Mandatory=$false, ParameterSetName='o2')]
[Parameter(Mandatory=$true, ParameterSetName='o3')]
[Switch][bool]$Switch3
)
如果你只使用其中一个开关,它就可以工作:
My-Function "foo" -Switch2
但如果您使用多个开关则会失败:
PS C:\> .\test.ps1 "foo" -Switch1 -Switch2
C:\test.ps1 : Parameter set cannot be resolved using the specified named
parameters.
At line:1 char:1
+ .\test.ps1 "foo" -Switch1 -Switch2
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [test.ps1], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,test.ps1
我将使用经过设置验证的强制参数:
Param(
[Parameter(Mandatory=$true)]
[string]$Text,
[Parameter(Mandatory=$true)]
[ValidateSet('Switch1', 'Switch2', 'Switch3', ignorecase=$true)]
[string[]]$Options
)
这将允许您像这样调用函数:
My-Function "foo" -Options Switch1
My-Function "foo" -Options Switch2,Switch3
或者你可以让所有三个开关都可选,并在函数内验证它们:
Param(
[Parameter(Mandatory=$true)]
[string]$Text,
[Parameter(Mandatory=$false)]
[Switch][bool]$Switch1,
[Parameter(Mandatory=$false)]
[Switch][bool]$Switch2,
[Parameter(Mandatory=$false)]
[Switch][bool]$Switch3
)
if (-not ($Switch1.IsPresent -or $Switch2.IsPresent -or $Switch3.IsPresent)) {
throw 'Missing switch'
}
Dynamic parameters可能是另一种选择,但我不能肯定地说。
答案 1 :(得分:0)
绝对有可能要求使用ParameterSet指定n个参数中的至少一个:
function My-Function() {
Param(
[Parameter(Mandatory, Position=0)]
[string]$Text,
[Parameter(Mandatory, ParameterSetName='o1')]
#not member of the following ParameterSets
[Switch][bool]$Switch1,
[Parameter(ParameterSetName='o1')] #non-mandatory member of previous ParameterSets
[Parameter(Mandatory, ParameterSetName='o2')]
#not member of the following ParameterSets
[Switch][bool]$Switch2,
[Parameter(ParameterSetName='o1')] #non-mandatory member of previous ParameterSets
[Parameter(ParameterSetName='o2')] #non-mandatory member of previous ParameterSets
[Parameter(Mandatory, ParameterSetName='o3')]
[Switch][bool]$Switch3
)
$PSBoundParameters
echo "`n"
}
#tests
echo "These should work:"
My-Function "some string" -Switch1 -Switch2 -Switch3
My-Function "some string" -Switch1 -Switch2
My-Function "some string" -Switch1 -Switch3
My-Function "some string" -Switch1
My-Function "some string" -Switch2 -Switch3
My-Function "some string" -Switch2
My-Function "some string" -Switch3
echo "This should not work:"
My-Function "some string"
echo "However, this does work:"
My-Function "some string" -Switch1:$false
但是,参数集仅强制要求在调用命令时使用其中一个开关。
未强制执行,实际上其中一个开关设置为true。 如果您需要这样做,请按照Ansgar Wiechers'answer(略有修改)中的建议在函数中进行实际测试:
if (-not ($Switch1.IsPresent -or $Switch2.IsPresent -or $Switch3.IsPresent)) {
#throw 'Missing switch' #not good, error message does not show where My-Function was called...
#Write-Error 'Missing switch' -ErrorAction Stop # better, but still stops the whole script, not just the function
$PSCmdlet.ThrowTerminatingError([System.Management.Automation.ErrorRecord]::new(
[System.Management.Automation.ParameterBindingException]'At least one of Switch1, Switch2, Switch3 must be true.',
'MissingRequiredSwitch',
[System.Management.Automation.ErrorCategory]::InvalidArgument,
$null
)) # statement-terminating error, same as generated when ParameterSet can not be resolved...
}
关于语句终止错误,请参见Difference between throw and $pscmdlet.ThrowTerminatingerror()?
但是,我仍然建议使用参数集(除了显式测试之外)。因为如上所述使用ParameterSets会使PSReadLine显示在自动完成信息中,所以至少需要一个参数。使用ctrl + space时的示例输出:
答案 2 :(得分:-1)
是的,你在定义时会parameter mandatory:
Param(
[Parameter(Mandatory=$true)]
[string]$myParameter
)