8

Given this basic function:

Function TestFunction {
    Param ( [int]$Par1, [string]$Par2, [string]$Par3 )
    If ($Par1 -ne $Null) { Write-Output "Par1 = $Par1" }
    If ($Par2 -ne $Null -or $Par2 -ne '') { Write-Output "Par2 = $Par2" }
    If ($Par3 -ne $Null) { Write-Output "Par3 = $Par3" }
}
TestFunction -Par1 1 -Par3 'par3'

...the output is:

Par1 = 1
Par2 = 
Par3 = par3

Even though I didn't pass anything into the $Par2 variable, it still isn't Null or empty. What happened, and how can I rewrite the statement so that the second If-statement evaluates as False and the script-block does not get executed?

(I added the -or $Par2 -ne '' just to test, it behaves the same with and without it.)

Mark
  • 339
  • 2
  • 4
  • 11

2 Answers2

13

You have a logic error in your program: $Par2 will always be not equal to $null or not equal to ''.

To fix the logic, you should use -and instead of -or here:

If ($Par2 -ne $Null -and $Par2 -ne '') { Write-Output "Par2 = $Par2" }

However, because you casted the $Par2 argument to a string in the function's argument list:

Param ( [int]$Par1, [string]$Par2, [string]$Par3 )
                    ^^^^^^^^

the check for $Par2 -ne $Null is unnecessary since $Par2 will always be of type string (if you do not give it a value, it will be assigned to ''). So, you should actually write:

If ($Par2 -ne '') { Write-Output "Par2 = $Par2" }

Or, because '' evaluates to false, you might just do:

If ($Par2) { Write-Output "Par2 = $Par2" }
  • That was fast. But what is actually IN `$Par2`? If I pass a value into it, `$Par2 -ne $Null` will be true. But if I pass nothing into it `$Par2 -ne $Null` should be false and should not be executed, right? And yet, it does... – Mark Apr 19 '15 at 01:44
  • See my edit. `$Par2` will always be a string because you casted it to one in the function's argument list. Also, for future, you can get the type of any variable using the `GetType` method: `$Par2.GetType()`. This will greatly aid in debugging. –  Apr 19 '15 at 01:49
  • So, because I casted it in the parameter-block, it will always exist and therefor never be null? Even if I were to change the default value into null (`[string]$Par2 = $Null`)? And an integer will always be 0? So if I were to pass nothing into `$par1`, then `If ($Par1)` will be true because it contains 0? So in trying to write a better script by casting the variable-types, I actually made it more difficult for myself. – Mark Apr 19 '15 at 01:59
  • Yes, that is correct. `$Par2` will never be `$null` because you casted it to a string. Even if you do `[string]$Par2 = $Null`, it will still be assigned to `''` (you can test this using `$Par2.GetType()`). And yes, `[int]$Par1 = $Null` will make `$Par1` become `0`. However, `If ($Par1)` will not be true because `0` evaluates to false in a boolean context (all other numbers evaluate to true). –  Apr 19 '15 at 02:10
  • I think I get it, thank you. You saved me from a headache. For completeness in this thread, I just discovered `[string]$Par2 = [System.Management.Automation.Language.NullString]::Value` to turn a string into null after all, now that I have an idea what to Google for. Although that doesn't work for integers. – Mark Apr 19 '15 at 02:18
1

You can check that (check if $variablename has $null as value):

if (!$variablename) { Write-Host "variable is null" }

And if you wanna check if $variablename has any value except $null:

if ($variablename) { Write-Host "variable is NOT null" }