Boolean Values in PowerShell

In PowerShell scripts, we often use logic to take some action based on the idea that something is true. But there may be situations where you need to handle the inverse. That is, situations where you need to know when something does not meet some criteria. While I personally find it easier to write and debug PowerShell that takes a more positive approach, it is important to understand negation. I thought I would spend a little time going through some of the more ‘negative’ aspects of PowerShell. Keep in mind that my recommended best practice when it comes to PowerShell scripting is that your code should flow freely, and simple is always better. There is almost always at least two ways to write any PowerShell command. You need to find the way that first solves your need and then is the most elegant.

Let’s start with some basics.

PowerShell Boolean Basics

When it comes to deciding if something ‘is’ or ‘isn’t’ in PowerShell, we are talking about Boolean values that are represented as $True or $False.

Boolean values in Windows PowerShell. (Image Credit: Jeff Hicks)
Boolean values in Windows PowerShell. (Image Credit: Jeff Hicks)

One thing I want to point out is that often $True and $False can be implicit. By that I mean, if something exists it can be said to have a value of $True. I realize there are some developers who might take exception to my interpretation. But I am not developing an application in Visual Studio. I am either running a command in the PowerShell console or writing a PowerShell script, so I have some latitude. Here’s what I’m talking about.

$p = get-process | where {$_.ws -gt 500mb}
if ($p) {
  #code to do something if processes found
}

In this example, I want to do something if there are processes with a working set size greater than 500MB. I don’t need to do any sort of comparison. If there is something in $p, the If expression will result in True. In a moment I’ll show you how we can turn this around. I also have corollary in that if you are evaluating a Boolean property, then you do not need to compare it to True or False. I’ve seen many examples of PowerShell beginners writing code like this:

$cs = Get-Ciminstance Win32_Computersystem -ComputerName chi-core01
if ($cs.PartOfDomain -eq $True) {
  #domain member code here
}
else {
    Write-Warning "Not a domain member"
}

Technically it works, but it is not what I consider elegant PowerShell. This example indicates, in my opinion, a lack of understanding of PowerShell. The PartofDomain property is a Boolean, which means all I really need is this:

if ($cs.PartOfDomain) {

You may think I’m splitting hairs, but something like this says a lot about the level of experience.

Not Operator

Now, there may be situations where you need to reverse or negate a comparison. This is where the –Not operator comes into play. You will also see the ‘!’ alias used. This operator reverses a Boolean value.
112514 2154 OneofTheseT3
You’ll often see this in situations with an If statement.

if (-Not (Test-Connection chi-fp01 -quiet)) {
  Write-Warning "CHI-FP01 is not online"
}

The Test-Connection cmdlet will return either True or False when used with –Quiet. If CHI-FP01 is not online, this would return $False. But I have a simple If statement that will only run if the parenthetical expression returns $True. Thus, I need to negate the result so that $False becomes $True. Note that I wrapped the Test-Connection command in parentheses. Using –Not can be tricky. You might need to speak aloud the logic of your statement to make sure you are using it properly. Depending on your needs, you may be able to structure your statements so that you don’t even need to use it.

NotContains

Another negative operator is –NotContains, which is the inverse of –Contains.

$a = "Alice","Bob","Charlie","Debra"
if ($a -notcontains "Jeff") {
  #add Jeff to the group
}

The comparison is to see if the value on the left does not contain the value on the right. This result will be a Boolean value. Be careful though because most often what you are testing for are simple values. Don’t try this:

$r = get-service | where {$_.status -eq 'running'}
if ($r -notcontains 'workfolderssvc') {
 #WorkFolders service is not in the collection
 Write-Warning "missing service"
}

The variable $r is a collection of service objects. The only way this would work would be to test if it doesn’t contain the object. Most of the times what scripters are really trying to do is this:

$r = get-service | where {$_.status -eq 'running'}
if ($r.name -notcontains 'workfolderssvc') {
 #WorkFolders service is not in the collection
 Write-Warning "missing service"
}

Now the test is for all of the Name property values in $r.

NotIn

Similar to –NotContains is –NotIn. The principal is the same except the test is turned around.

$range = 1..7
[int]$i = Read-Host "Enter the number of days"
if ($i -notin $range) {
    Write-Warning "I can't do that."
}

Now I’m testing to see if the number, $i, is not in the $range. Whether you test for –NotContains or –NotIn comes down to what makes the most sense in your script and is a much a style decision as anything.

NotLike and NotMatch

Finally, we have the regular expression comparison operators. The –Notlike operator does a string comparison using wildcards.

get-process | where { $_.Company -notlike "*Microsoft*"} | select name,company

Using the -NotLike operator in Windows PowerShell. (Image Credit: Jeff Hicks)
Using the -NotLike operator in Windows PowerShell. (Image Credit: Jeff Hicks)

 
Or you can use a regular expression pattern.

get-process | where { $_.Company -notmatch "^Microsoft"} | select name,company

I know there are ways to construct the regular expression pattern to also include negation, but often I find it easier to simply use the –NotMatch operator.
If you look at the screenshot above, you’ll see I have some blanks because there are some processes that don’t have a value for the Company property. Here’s a revised solution.

get-process | where { $_.Company -AND $_.Company -notmatch "^Microsoft"} | select name,company

I am using a compound filter that can be read: “If the Company property has a property, and thus True, AND the Company property does not match the regular expression pattern for Microsoft, then pass the object down the pipeline.”

A Boolean example in Windows PowerShell. (Image Credit: Jeff Hicks)
A Boolean example in Windows PowerShell. (Image Credit: Jeff Hicks)

 

All of the operators I’ve discussed, as well as their positive counterparts are documented in the PowerShell about topics, which I encourage you to read.