Search code examples
powershellpowershell-4.0

Powershell if statement


In one of my servers we have an program that we need to update each month, this program is running on a terminal server.

My basic script is working (it's very simple):


Get-SmbOpenFile |where {$_.Path -eq "D:\Shares\Programs\test.exe"} |select ClientUserName, path |ft -autosize

pause

But i'am trying to make it more "smarter" so I've tried to use the IF statement:

First test:

$open = Get-SmbOpenFile |where {$_.Path -eq "D:\Shares\Programs\test.exe"} |`
select ClientUserName, path |ft -autosize



if ($open -eq "true")
{ write-host "showing open files"
}

elseif ($open -eq "false")
{ "All cloesd"
}

pause

Second test:

$open = Get-SmbOpenFile |where {$_.Path -eq "D:\Shares\Programs\test.exe"} |`
select ClientUserName, path |ft -autosize


if ($open -eq $true)
{
 write-host "showing open files"
}

elseif ($open -eq $false)
{ 
"All cloesd"
}

I've also tried to define the variable in that way:

$open = Get-SmbOpenFile |where {$_.Path -eq "D:\Shares\Programs\test.exe"} 

I'am not getting actually any output at all when i use the IF statement.

Thanks a lot for your help !


Solution

    • Only ever use Format-* cmdlets such as ft (Format-Table) for display formatting; never use them if data must be programmatically processed. Format-* cmdlets output formatting instructions, not data - see this answer.

    • Even with | ft -autosize removed, you shouldn't compare $open to $true or $false, because such an explicit comparison will not generally work as intended if the LHS isn't already a Boolean (type [bool])[1]; instead, take advantage of PowerShell's implicit to-Boolean conversion - see the bottom section of this answer.

    • Your if branch doesn't actually output $open; it only outputs a Write-Host status message to the display.

    To put it all together:

    $open = Get-SmbOpenFile | 
              Where-Object {$_.Path -eq "D:\Shares\Programs\test.exe"} |
                Select-Object ClientUserName, Path
    
    if ($open) {
      Write-Host "showing open files"
      $open  # output the result
    }
    else {
      Write-Host "all closed"
    }
    

    Select-Object returns either:

    • a [pscustomobject] instance[2] (a custom object with properties .ClientUserName and .Path)

      • Any [pscustomobject] instance - regardless of its structure - evaluates to $true in a Boolean context.
    • or "nothing" (technically, [System.Management.Automation.Internal.AutomationNull]::Value), if the Where-Object cmdlet didn't find the specified path in Get-SmbOpenFile's output.

      • "Nothing" evaluates to $false in a Boolean context.

    Again, see the bottom section of this answer for the complete set of rules of implicit to-Boolean conversion.


    [1] Notably, a non-primitive object as the LHS always yields $false when compared to $true (though not with the operands reversed); e.g., (Get-Item /) -eq $true; also, any nonzero number that isn't exactly 1 will indicate $false; e.g.: 2 -eq $true. Additionally, with an array-valued LHS, -eq acts as filter, returns the subarray of matching items (e.g., (1, 2, 1) -eq $true returns 1, 1.

    [2] In general, Select-Object can return multiple objects, in which case $open would receive an[object[]]-typed array of [pscustomobject] instances. An array with 2 or more elements is always $true in a Boolean context.