【问题标题】:Can I make one parameter mandatory based on the _value_ of a different parameter?我可以根据不同参数的 _value_ 强制一个参数吗?
【发布时间】:2020-06-14 02:01:06
【问题描述】:

如果参数一设置为 bbb,那么我想强制参数二。是否可以以某种方式使用参数集来做到这一点,还是我只需将此逻辑添加到脚本本身?

我需要的示例:

 param (
        [Parameter(Mandatory, ParameterSetName = 'default')]
        [ValidateSet(“aaa”, ”bbb”, ”ccc”, "ddd")]
        [String]
        $One,

        [Parameter(ParameterSetName = 'default')]
        [ValidateScript( { $One -eq 'bbb'; THEN MAKE THIS PARAM MANDATORY! })]
        [String]
        $Two
    )

$One 的值似乎尚未设置,因为我尝试这样做并且 one.txt 为空

[ValidateScript( { $One > One.txt; $true })]

编辑

虽然有 DynamicParam{},但只有在您进行了开始、处理、结束等设置时才看起来像它。这是一个简单的功能,我不想添加它。此外,DynamicParam 似乎需要大量的样板代码才能工作

编辑

看起来 DynamicParam 是唯一的方法,但我认为它很疯狂。这很奇怪且不可读,但我仍然更喜欢 Powershell 为我处理验证。

自己做还是很简单的:

if ($One -eq 'bbb' -and -not $Two) {
    ThrowError Param Two required when One set to $One
}

【问题讨论】:

  • 看起来 DynamicParam 需要 PROCESS 虽然我不想使用
  • 没有进程块它会工作。查看答案。

标签: function powershell parameters


【解决方案1】:

您正在寻找动态参数:Conditional PowerShell parameters

param( 
  [String]$One
)

DynamicParam {
  # Create a parameter dictionary
  $runtimeParams = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary

  # Populate it with parameters, with optional attributes

  $attribs = New-Object  System.Collections.ObjectModel.Collection[System.Attribute]

  $mandatoryAttrib = New-Object System.Management.Automation.ParameterAttribute
  $mandatoryAttrib.Mandatory = ($one -eq "bbb")
  $attribs.Add($mandatoryAttrib)

  $param = New-Object System.Management.Automation.RuntimeDefinedParameter('Two', String, $attribs)
}
Begin {
  # If desired, move dynamic parameter values to variables
  $ParameterName = $PSBoundParameters['Two']
}

  # Do like regular

没有进程块它会工作。

【讨论】:

  • 我收到错误表达式或语句中的意外令牌'}'。应该是$param = New-Object System.Management.Automation.RuntimeDefinedParameter('Two', [string], $attribs
  • 这似乎也不起作用。如果 One=bbb 没有引发任何错误,则不指定参数二
  • 虽然使用动态参数是可能的——如果相当冗长的话——解决方案,请确保您的代码在发布之前确实有效:它不仅完全被破坏(调用失败),而且缺少关键部分。
【解决方案2】:

通过使用Throwif 语句,使用参数-Two默认值 来强制执行所需的逻辑

param (
  [Parameter(Mandatory, ParameterSetName = 'default')]
  [ValidateSet('aaa', 'bbb', 'ccc', 'ddd')]
  [String]
  $One,

  [Parameter(ParameterSetName = 'default')]
  [String]
  $Two = $(if ($One -eq 'bbb') { Throw "-Two must be passed if -One equals 'bbb'." })
)

"-One: $One; -Two: $Two"

注意:模拟带有Throw 的(有条件的)强制参数意味着该行为与常规Mandatory 参数的不同之处在于后者提示当一个值没有给出。

基于验证属性的解决方案会更可取,但验证属性不是为交叉参数验证而设计的,并且不能保证其评估的特定顺序。

上述解决方案依赖于默认值在显式传递的参数被绑定后评估的事实。

更详细的替代方法是使用 dynamic parameter,如Wasif Hasan's answer 所示,依赖于相同的时间,尽管它确实具有展示正常提示的优势-缺失强制值行为。

在撰写本文时,Wasif 的答案并没有像发布的那样起作用,所以这是一个可行的解决方案;注意DynamicParam 的使用在语法上需要beginprocessend 块(至少其中之一)

# Syntax requires PSv5+:
using namespace System.Management.Automation

param( 
  [Parameter(Mandatory, ParameterSetName='default')]
  [ValidateSet('aaa', 'bbb', 'ccc', 'ddd')]
  [String]$One
)

# Define parameter -Two *dynamically*, so that its Mandatory property
# can be based on the specific value of the already-bound static -One parameter.
DynamicParam {

  # Create a the dictionary of dynamic parameters.
  $dict = [RuntimeDefinedParameterDictionary]::new()

  # Define and add the -Two parameter 
  $paramName = 'Two'
  $dict.Add(
    $paramName,
    [RuntimeDefinedParameter]::new(
      $paramName,
      [string],
      [ParameterAttribute] @{
        ParameterSetName = 'default'
        # *Conditionally* make the parameter mandatory, depending on the value
        # of the already-bound static -One parameter.
        Mandatory = $One -eq 'bbb'
      }
    )
  )

  # Return the dictionary
  return $dict
}

begin {

  # NOTE: Dynamic parameter values do not become local variables the way
  #       they do for static parameters; the value must be accessed via the
  #       automatic $PSBoundParameters dictionary.
  $Two = $PSBoundParameters['Two']

  "-One: $One; -Two: $Two"

}

【讨论】:

  • 完美。可能不像实际的验证器语法那样具有声明性,但我喜欢让它与参数本身而不是脚本主体一起使用
  • +1,非常努力。谢谢!我需要通过深入的 powershell 知识来丰富自己。该死的,我希望我能像你和我们的爱好者一样写答案。我没有使用 ParameterSet 是因为我认为它基于另一个参数的存在将一个参数与另一个参数绑定。所以我没有在我的答案中使用它。但是你已经展示了如何去做。再次感谢您纠正我的回答。
  • 感谢@WasifHasan 的良好反馈,但请考虑修复您的答案,因为无论偶然的参数设置问题如何,代码根本不起作用,而且不会对于未来的读者来说,如何解决它是显而易见的。
猜你喜欢
  • 1970-01-01
  • 2016-05-17
  • 1970-01-01
  • 2018-12-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
相关资源
最近更新 更多