How do I distinguish an unset parameter from $ false, 0, an empty string?

I have a function that updates an object in WMI. I want the user to be able to specify in the parameters only the values ​​that he wants to update. How can i do this?

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.
}

      

I tried passing $null

as a parameter, but it is automatically converted to $false

for bool

, 0

for int

and empty string

forstring

What are your suggestions?

+3


source to share


4 answers


Check $PSBoundParameters

to see if it contains a key with your parameter name:

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

acts like a hash table where keys are parameter names and values ​​are parameter values, but they only contain associated parameters, which means explicitly passed parameters. It does not contain parameters filled with a default value (other than those passed by $PSDefaultParameterValues

).

+4


source


Based on briantist's answer , if you know that all parameters exist as properties of the target, you can just loop through the hash table $PSBoundParameters

and add them one by one:

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

      




If only some of the input parameters need to be passed as property values, you can still specify the list only once using:

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

      

+2


source


If you want to specify a parameter [Boolean]

that you want to be explicitly specified or omitted (rather than a parameter [Switch]

that may or may not be present), you can use [Nullable[Boolean]]

. Example:

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"
  }
}

      

In this example function, the variable $Test

would be $null

(user specified no parameter), $true

(user specified -Test $true

), or $false

(user specified -Test $false

). If the user specifies -Test

without a parameter argument, PowerShell will throw an error.

In other words: This gives you a tri-state parameter [Boolean]

(missing, explicitly true, or explicitly false). [Switch]

gives only two states (present or explicitly true, absent or explicitly false).

+1


source


To save yourself the trouble of creating a parameter for every property that you can change, consider using a hash table or other object to pass this information to your function.

For example:

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}

      

+1


source







All Articles