【问题标题】:How to differentiate not set parameter from $false, 0, empty string?如何区分未设置参数与 $false、0、空字符串?
【发布时间】:2018-01-16 05:27:45
【问题描述】:

我有在 WMI 中更新对象的函数。我希望用户能够在参数中仅指定他想要更新的值。我该怎么做?

function UpdateObject ([bool] $b1, [bool] $b2, [int] $n1, [string] $s1)
{
    $myObject = GetObjectFromWmi #(...)
    #(...)

    #This is bad. As it overrides all the properties.
    $myObject.b1 = $b1
    $myObject.b2 = $b2
    $myObject.n1 = $n1
    $myObject.s1 = $s1

    #This is what I was thinking but don't kwow how to do
    if(IsSet($b1)) { $myObject.b1 = $b1 }
    if(IsSet($b2)) { $myObject.b2 = $b2 }
    if(IsSet($n1)) { $myObject.n1 = $n1 }
    if(IsSet($s1)) { $myObject.s1 = $s1 }

    #(...) Store myObject in WMI.
}

我尝试将$null 作为参数传递,但它会自动转换为$false 用于bool0 用于intempty string 用于string

你有什么建议?

【问题讨论】:

    标签: powershell powershell-2.0 powershell-3.0 powershell-4.0


    【解决方案1】:

    检查$PSBoundParameters 以查看它是否包含带有您的参数名称的键:

    if($PSBoundParameters.ContainsKey('b1')) { $myObject.b1 = $b1 }
    if($PSBoundParameters.ContainsKey('b2')) { $myObject.b2 = $b2 }
    if($PSBoundParameters.ContainsKey('n1')) { $myObject.n1 = $n1 }
    if($PSBoundParameters.ContainsKey('s1')) { $myObject.s1 = $s1 }
    

    $PSBoundParameters 就像一个哈希表,其中键是参数名称,值是参数的值,但它只包含 bound 参数,这意味着显式传递的参数。它不包含用默认值填充的参数(除了那些用$PSDefaultParameterValues传递的参数)。

    【讨论】:

    • 这正是我想要的。谢谢。
    【解决方案2】:

    briantist's answer 的基础上,如果您知道所有参数都作为属性存在于目标对象上,您可以简单地遍历$PSBoundParameters 哈希表并一一添加:

    foreach($ParameterName in $PSBoundParameters.Keys){
        $myObject.$ParameterName = $PSBoundParameters[$ParameterName]
    }
    

    如果只有 一些 输入参数作为属性值传递,您仍然可以只指定一次列表,其中:

    $PropertyNames = 'b1','b2','n1','s1'
    foreach($ParameterName in $PSBoundParameters.Keys |Where-Object {$PropertyNames -contains $_}){
        $myObject.$ParameterName = $PSBoundParameters[$ParameterName]
    }
    

    【讨论】:

    • 这很好。该函数还有更多参数,我在很多地方都不需要。但是请接受我的投票,因为这确实是我将来可能会使用的巧妙解决方案。
    【解决方案3】:

    为了避免为您可能要更改的每个属性创建参数,请考虑使用哈希表或其他对象将此信息传递给您的函数。

    例如:

    function UpdateObject ([hashtable]$properties){
    
        $myObject = GetObjectFromWmi
    
        foreach($property in $properties.Keys){
    
            # without checking
             $myObject.$property = $properties.$property
    
            # with checking (assuming members of the wmiobject have MemberType Property.
            if($property -in (($myObject | Get-Member | Where-Object {$_.MemberType -eq "Property"}).Name)){
                Write-Output "Updating $property to $($properties.$property)"
                $myObject.$property = $properties.$property
            }else{
                Write-Output "Property $property not recognised"
            }
    
        }
    }
    
    UpdateObject -properties {"b1" = $true; "b2" = $false}
    

    【讨论】:

    • 就个人而言,我认为这种方法会削弱您的功能。当您在设计时不知道参数应该是什么时,当它们是动态的时,这是有道理的,但它绕过了 PowerShell 为管理参数所做的所有事情,并且使所有这些都不太容易被发现。它会破坏自动生成的帮助等。
    • @briantist 感谢您的反馈。我发现您的答案最接近 OP 在 +1 之后的答案。还同意,当参数已知且内置参数优势时,最好使用少量参数。但是,在类似的情况下,我发现为每个可能更改(并在后续更新)的属性创建参数是一场噩梦。尤其是在考虑大量属性时,AFAIK 是 WmiObjects 的情况。在这种情况下,我更喜欢哈希表的多功能性,因为实际上限制是GetObjectFromWmi(使用 OP 的示例)
    • 如果真正的意图是支持所有可能的 WMI 属性,或者其中的很大一部分,那么我会同意。如果包装函数支持特定的已知目的,那么我认为最好显式创建参数。由于示例函数不是传递的要更新的对象,也不是有关检索(变量)对象类型的信息,而是检索其中的对象(不使用传递的参数),因此 WMI obj 类型似乎很可能是已知的,所以对我来说似乎更适合明确声明。这是明显的。一个例子 func 但谁知道呢!
    【解决方案4】:

    如果您希望用户明确指定或省略[Boolean] 参数(而不是可以存在或不存在的[Switch] 参数),您可以使用[Nullable[Boolean]]。示例:

    function Test-Boolean {
      param(
        [Nullable[Boolean]] $Test
      )
    
      if ( $Test -ne $null ) {
        if ( $Test ) {
          "You specified -Test `$true"
        }
        else {
          "You specified -Test `$false"
        }
      }
      else {
        "You did not specify -Test"
      }
    }
    

    在此示例函数中,$Test 变量将为$null(用户未指定参数)、$true(用户指定-Test $true)或$false(用户指定-Test $false)。如果用户指定-Test 而不带参数参数,PowerShell 将抛出错误。

    换句话说:这为您提供了一个三态[Boolean] 参数(缺失、明确为真或明确为假)。 [Switch] 只为您提供两种状态(存在或明确为真,不存在或明确为假)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-27
      • 2020-01-31
      • 2015-02-15
      • 1970-01-01
      • 1970-01-01
      • 2014-10-01
      相关资源
      最近更新 更多