如何强制指定集合中的至少一个参数?

时间:2015-11-30 14:12:41

标签: powershell

我有一个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对象传递开关来实现此目的,但有没有办法使用ParameterParameterSet属性执行此操作?

简而言之,这就是我想要做的事情:

  • 每次调用函数时都必须提供字符串。
  • 每次调用该函数时,必须至少提供一个开关。

3 个答案:

答案 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时的示例输出:

enter image description here

答案 2 :(得分:-1)

是的,你在定义时会parameter mandatory

 Param(
   [Parameter(Mandatory=$true)]
   [string]$myParameter
)