Getting Where-Object to filter correctly


I have a script that checks for iLO firmware versions and updates if they are not running the latest versions.

I’m getting some strange behavior when using Where-Object to check for firmware versions.

For example, the below works fine, and on a server with the firmware versions listed nothing is returned:

$global:iLOType = (Find-HPEiLO -Range $global:iLOs -WarningAction SilentlyContinue).PN
$global:iLO3fwVersion = "1.91"
$global:iLO4fwVersion = "2.61"

$foundServers = Find-HPEiLO -Range $global:iLOs | Where-Object {($_.PN -EQ $global:iLOType) -and ($_.FWRI -NE $global:iLO4fwVersion) -or ($_.PN -EQ $global:iLOType) -and  ($_.FWRI -NE $global:iLO3fwVersion)}

However, I wanted to add a check for iLO 5 machines so added:

$foundServers = Find-HPEiLO -Range $global:iLOs | Where-Object {($_.PN -EQ $global:iLOType) -and ($_.FWRI -NE $global:iLO4fwVersion) -or ($_.PN -EQ $global:iLOType) -and  ($_.FWRI -NE $global:iLO3fwVersion) -or ($_.PN -EQ $global:iLOType) -and ($_.FWRI -NE $global:iLO5fwVersion)}
But now when the script is run the script outputs the following to the $foundservers variable:
FWRI       : 1.91
PN         : Integrated Lights-Out 3 (iLO 3)
Have tried a couple of different options to get this to work such as:
Find-HPEiLO -Range $global:iLOs | Where-Object {($_.PN -EQ $global:iLOType) -and ($_.FWRI -ne (
$global:iLO3fwVersion) -or ($global:iLO4fwVersion) -or ($global:iLO5fwVersion))}
Find-HPEiLO -Range $global:iLOs | Where-Object {($_.PN -EQ $global:iLOType) -and (($_.FWRI -ne 
$global:iLO3fwVersion) -or ($_.FWRI -ne $global:iLO4fwVersion) -or ($_.FWRI -ne $global:iLO5fwVersion))}
But all seem to output the FWRI and PN values regardless.

Here’s a link to the full script for completeness:!AvSxePbq1EpYq51IHeTBX8A9zojk7g

how does this do ?

$foundServers = Find-HPEiLO -Range $global:iLOs | Where-Object {
    ($_.PN -EQ $global:iLOType) -and ($global:iLO3fwVersion, $global:iLO4fwVersion, $global:iLO5fwVersion -notcontains $_.FWRI)

I’m not really sure what all the variables are, but -and and -or will be evaluated left to right unless you add some parentheses. You might think -and would have a stronger precedence than -or, like in other languages. I think you accidentally got the result you wanted in the first case because of this.

$true -and $true -or $true -and $false                             

$true -and $true -or $true -and $false -or $true -and $true        

($true -and $true) -or ($true -and $false)                         

($true -and $true) -or ($true -and $false) -or ($true -and $true)  

Thanks for the replies.

Tom_Mort_Yates - Many thanks that worked like a charm!

And js thanks for the clarification on how the -if -or works.