至少设置 PowerShell 所需的众多参数之一

sta*_*tor 3 parameters powershell optional-parameters powershell-5.1

在 PowerShell 中,我想编写一个函数,它接受不同的选项作为参数。如果它接收多个参数是可以的,但它必须至少接收一个参数。我想通过参数定义来强制执行它,而不是通过之后的代码。我可以使用以下代码让它工作:

function Set-Option {

    Param(
        [Parameter(Mandatory, ParameterSetName="AtLeastOption1")]
        [Parameter(Mandatory=$false, ParameterSetName="AtLeastOption2")]
        [Parameter(Mandatory=$false, ParameterSetName="AtLeastOption3")]
        $Option1,

        [Parameter(Mandatory=$false, ParameterSetName="AtLeastOption1")]
        [Parameter(Mandatory, ParameterSetName="AtLeastOption2")]
        [Parameter(Mandatory=$false, ParameterSetName="AtLeastOption3")]
        $Option2,

        [Parameter(Mandatory=$false, ParameterSetName="AtLeastOption1")]
        [Parameter(Mandatory=$false, ParameterSetName="AtLeastOption2")]
        [Parameter(Mandatory, ParameterSetName="AtLeastOption3")]
        $Option3
    )

    # Do stuff, but don't evaluate the plausibility of the given parameters here
}
Run Code Online (Sandbox Code Playgroud)

但正如您所看到的,它的扩展性很差。对于每个附加选项,我必须向所有其他选项添加一行。能否以更高效且更可维护的方式来完成此操作?

正如我已经说过的,我不想检查代码中的参数,例如通过评估$PSBoundParameters. 出于自动文档的原因,我希望它发生在参数定义中。


如果您需要一个真实世界的示例,请查看Set-DhcpServerv4OptionValue它接受许多不同的选项(-DnsDomain-DnsServer-Router、 ...),其中可以包含所有选项,但没有任何选项是没有意义的。


注意:在提供了几个答案之后,我刚刚意识到,如果您提供多个选项,我的代码实际上不起作用。

mkl*_*nt0 5

以下不是一个很好的解决方案 - 根据您对auto-doc 的含义,它可能不适合您 - 但它可以很好地扩展,因为您只需要一个额外的参数集:

function Set-Option {

  [CmdletBinding(DefaultParameterSetName='Fail')]
  Param(
      [Parameter(ParameterSetName='AtLeastOne')]
      $Option1,

      [Parameter(ParameterSetName='AtLeastOne')]
      $Option2,

      [Parameter(ParameterSetName='AtLeastOne')]
      $Option3,

      # Declare a dummy parameter whose default value throws an error
      # if no other parameter is passed.
      # Note: All that 'DontShow' does is to exclude the parameter
      #       from tab completion; doesn't hide it from syntax diagram.
      [Parameter(ParameterSetName='Fail', DontShow)] 
      ${-} = $(
        if ($PScmdlet.ParameterSetName -eq 'Fail') { 
          throw "Please specify at least one option." 
        }
      )
  )

  # Do stuff, without needing to evaluate the plausibility of
  # the given parameters here.

}
Run Code Online (Sandbox Code Playgroud)
  • 所有实际参数都是可选的,并且属于默认的同一参数集。

  • ${-}虚拟参数是默认参数集中唯一的一个,其目的只是通过其默认值抛出错误。

    • 由于总是评估默认值,因此仅当选择了默认参数集 ( ) 时才需要抛出条件$PScmdlet.ParameterSetName -eq 'Fail'

    • 由于参数的名称不规则,您实际上无法向它传递显式值(这在这里是可取的,因为它纯粹是辅助的,不适合直接使用):您必须使用-- <value>, 但--对参数绑定器有特殊含义(停用后续参数的命名参数绑定)。

    • 不幸的是,属性DontShow(例如)仅隐藏制表符完成[Parameter(DontShow)]中的参数,而不是语法图中的参数。

因此,不幸的是,虚拟参数集及其参数出现在语法图中,因此Set-Option -?显示如下:

SYNTAX
    Set-Option [-- <Object>] [<CommonParameters>]

    Set-Option [-Option1 <Object>] [-Option2 <Object>] [-Option3 <Object>] [<CommonParameters>]
Run Code Online (Sandbox Code Playgroud)

请注意,语法图缺少您所需逻辑的符号。