Search code examples
windowspowershelliscsi

Can not compare Values of Variable with strings in Powershell


I am trying to get info about an iSCSI-Targets Connectionstate.

Ideally I want to have a variable with a value that is True or False for connected or not connected, so that i can run commands to connect or disconnect as needed.

If i set the Variable directly it's working fine. Setting the Variable with the output of a cmdlet seems to work but comparing the Values False or True with IF is always resulting in True. For me the question is: where is the difference between setting the Variable directly to True and using the output of the cmdlet...?

Sample one:

$IsConnected=true

if($IsConnected -eq 'true') {
    echo IsConnected!
} else {
    echo IsNotConnected
}

Results, as expected, in: IsConnected

Sample two:

$IsConnected=False
if($IsConnected -eq 'true') {
    echo IsConnected!
} else {
    echo IsNotConnected
}

Results, as expected, in: IsNotConnected

So now my knowledge ends...:

Sample three:

PS ~> $IsConnected=get-iscsitarget | select -ExpandProperty IsConnected
PS ~> echo $IsConnected
True
PS ~> if($IsConnected -eq 'True') {Echo "IsConnected"}else{echo "IsNotConnected"}
IsConnected
PS ~> if($IsConnected -eq 'False') {Echo "IsConnected"}else{echo "IsNotConnected"}
IsConnected
PS ~> if($IsConnected -eq '17beerarenotenaugh') {Echo "IsConnected"}else{echo "IsNotConnected"}
IsConnected

Solution

  • PowerShell's comparison operators are overloaded, meaning they might have different behaviors based on the type of operand you provide.

    The behavior depends entirely on the type of the left-hand side (lhs) operand you provide, and PowerShell will try to convert the right-hand side (rhs) to the same.

    In your example, the value of the $IsConnected variable is a [bool] - and PowerShell therefore attempts to convert the rhs operand to a [bool] to.

    The conversion logic for [string] to [bool] is:

    • Empty strings = $false
    • Non-empty strings = $true

    Since 'True', 'False' and '17beerarenotenaugh' are all non-empty, the if conditions are basically interpreted as:

    if($IsConnected -eq $true) { ... }
    if($IsConnected -eq $true) { ... }
    if($IsConnected -eq $true) { ... }
    

    Use the automatic variables $true and $false to avoid this:

    PS ~> if($IsConnected -eq $false) {Echo "IsConnected"}else{echo "IsNotConnected"}
    IsNotConnected
    

    alternatively, use the -not operator:

    PS ~> if(-not $IsConnected) {Echo "IsConnected"}else{echo "IsNotConnected"}
    IsNotConnected