如何区分未设置参数与 $false、0、空字符串?

How to differentiate not set parameter from $false, 0, empty string?

我有更新 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 作为参数传递,但它自动转换为 bool$falseint 和 [=16= 的 0 ] string

你有什么建议?

检查 $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 传递的参数除外)。

如果您想要一个 [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] 只给你两种状态(存在或明确为真,不存在或明确为假)。

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

例如:

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}

的基础上,如果您知道所有参数都作为目标对象的属性存在,您可以简单地遍历 $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]
}