Tuesday, March 11, 2014

PowerShell testing empty parameters with if and $false

I just ran into the most interesting behavior.  I say that because I never ran into it before.

In many of my scripts I evaluate to see if a value has been passed in order to decide if I am going to process something.

Within my scripts it simply looks like this:

if ($VirtualMachineMigration) { }

If this parameter contains something, then act upon that something.  The reverse is to use the not:

if (!$VirtualMachineMigration) { }

If this parameter contains nothing, then do something.

Today I learned that this works all well and fine with strings, and objects, and integers, etc.  But not so well with Booleans.

Lets take a look at the following:

function EnableVMMigration
{
    [CmdletBinding()]
    param
    (
        [System.Boolean]
        $VirtualMachineMigration
    )

    if ($VirtualMachineMigration) {
        "in my If, making my next decision"
    }
    "Out of my IF"
}

That is simple enough, it accepts a Boolean parameter of VirtualMachineMigration.  Lets give it a go:

First give it a $true:

PS C:\Users\Administrator\Documents> EnableVMMigration -VirtualMachineMigration $true
in my If, making my next decision
Out of my IF

Exactly as I expected.

Now, give it a $false

PS C:\Users\Administrator\Documents> EnableVMMigration -VirtualMachineMigration $false
Out of my IF

It never even entered my if statement.  Because the If is $false, because I am sending it one – although the condition of the evaluation of ‘is $VirtualMachineMigration’ empty is actually no different than it was when it was $true.

So, what is happening?  PowerShell is simply evaluating the parameter itself, not the question of ‘is this empty’.

Tricky little shell.

So, what if I really want to check if this is empty and the possibility is either $true or $false?  (this is my first idea to work around this, I am sure that there are others)

So, lets update the function so that I truly see if the parameter is empty before deciding how to act on whether it is $true or $false

function EnableVMMigration
{
    [CmdletBinding()]
    param
    (
        [System.Boolean]
        $VirtualMachineMigration
    )

    if ($VirtualMachineMigration) {
        "making a positive choice"
    }
    elseif (!$VirtualMachineMigration) {
        "Making a negative choice"
    }
    "Out of my IF"
}

PS C:\Users\Administrator\Documents> EnableVMMigration -VirtualMachineMigration $true
making a positive choice
Out of my IF

PS C:\Users\Administrator\Documents> EnableVMMigration -VirtualMachineMigration $false
Making a negative choice
Out of my IF

Now, that works the way I wanted it to.

3 comments:

BrianEh said...

I already realize that I am not quite right in this post and my next post will explain why.

As long as you always pass $true or $false this works.

But, what happens if the parameter is not passed, if the parameter is left empty...

Guenther Schmitz said...

hi!
you could make the parameter mandatory:

[CmdletBinding()]
Param (
[Parameter(Mandatory=$true,Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$True)]
[System.Boolean]$VirtualMachineMigration
)

or preset it if it is not set
[CmdletBinding()]
Param (
[Parameter(Mandatory=$false,Position=0,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$True)]
[System.Boolean]$VirtualMachineMigration = $false
)

KR
Guenther

BrianEh said...

Yes, making the parameter mandatory is one solution.

Thus not allowing the parameter to be empty in the first place.