Let’s paint a picture, and since I’m no Bob Ross it’s paint by numbers time. More specifically let’s talk about binary numbers. This post assumes you have a basic understanding of the binary numbering system (or base 2). If you’re not familiar you should read this.
Back to the picture - it’s all lightswitches. A load of them.
So we want a way to represent the status of all of these lightswitches and easily look up a value. “Easy,” you say, “we’ll just make a table!”
Switch | Value -------------- 9 | 1 8 | 1 7 | 1 6 | 0 5 | 0 4 | 0 3 | 0 2 | 1 1 | 1
Great, but now we need to store this data somewhere. Everytime we paint this picture, err, write this table out it takes an entire post-it note. Not super efficient. What if we could condense the value of all the switches to a single line. Is there a way we could do this in a single line since we already know their position?
Perfect. We could condense this even further and just say 451 since 111000011 in binary is 451 in decimal (base 10). We lose quite a bit of readability here, but we’ve just now represented the setting of 9 different switches with 3 numbers.
In What World Does This Provide Any Value?
It’s about saving space. Digital space. Bits. In the example above we talked about post-it notes, but what if you had to communicate the value of the lightswitches to thousands of people? Would you want to write out the table for each person or would you rather just write 451 on each post-it note and let your receiver decipher its meaning? I’d prefer the latter as it would take me a lot less time to complete.
So let’s exit the analogy and get into the world of applications. Suppose you had a handful of settings you wanted to define for something in an application. You could most certainly define each of these settings in their own column in a database, but what happens when you need to add a new setting? Well now you need to modify the table to add a new column.
By storing these values in a long long number (64bits) you now have 64 possible settings you can store in a single number. So if you have only 10 settings now, you still have space for an additional 54 of them in the long long term (bad pun… I apologize for nothing).
But how do we get the value of the individual settings?
Enter “Bitwise AND”, stage right.
Bitwise AND - or bAnd for short
The fun part about binary is that every position is defined by a unique decimal value that can’t be replicated by any other combination of positions. What I mean is - the second position in binary is equal to 2 which can only be represented by 10 in binary. It can’t be represented by 11 or 100 or 101… 2 can ONLY be represented by 10.
With this possibly newfound information we can do some fun things. One of which involves the bitwise and operation. No cheating - what do you think the value of the following PowerShell expression might be?
5 -bAnd 4
If you said 4 - you would be correct. Here’s why. The “and” operation looks for bits in the number that are both “on” in their respective position and returns that result. A visual representation would look like this:
101 (Decimal 5) 100 (Decimal 4) --- -bAnd 100 (Decimal 4)
Notice that the only position that has a shared “on” is position 3.
Look at a bit larger example and it might become a bit more clear:
11011010 (Decimal 218) 10101010 (Decimal 170) -------- -bAnd 10001010 (Decimal 138)
Now how do we apply this to settings? Let’s take a look at an example from ConfigMgr - since this blog is heavily focused on it and also happens to be the reason for this post.
A task sequence stores a group of settings in a property called “Program Flags”. The settings that are defined in this property are listed here (make sure to search for “ProgramFlags”). This property is an unsigned 32-bit integer - meaning we have 32 potential options to play with (of which 30 are detailed with a few not being used). Let’s pick a value from the list - we’ll say “DISABLED” - again this being what spawned this blog post. We know that the value of DISABLED is defined as the 13th position in binary or 0x00001000 in hexadecimal. Since the hexidecimal value is already provided to you, it will be easiest to -bAnd with that.
First we get the value of ProgramFlags from the TS.
And then we run a bitwise and (-bAnd) against it in PowerShell.
152088592 -bAnd 0x00001000 (yes the hexidecmal notation will work in PowerShell)
And we get a value of 4096 (the 13th position in binary - 0001 0000 0000 0000). So we know that this particular task sequence is disabled. If the value was a 0 instead, we would know that the task sequence is NOT disabled (or rather it is enabled).
So now we know how to retrieve a value, but what if we want to enable a setting (or multiple settings at once)?
Enter “Bitwise OR”, stage left.
Bitwise OR - or bOr for short
Think to yourself for a moment - what does the OR comparison operator in PowerShell do?
It takes two booleans ($True or $False) and if either of them is $True then the or ALSO returns $True. If both are $False then it returns $False. So now think to yourself again… what might the -bOr operator do?
You’re right. Whenever a bit is “ON” between two numbers then the result is a 1. Like this:
0101 1001 ---- -bOr 1101
So if we knew we wanted to disable a task sequence, we could just -bOr the program flag setting and now we would know the new value that should be set for ProgramFlags.
152088592 -bOr 0x00001000
In this case it would still return 152088592 since the task sequence in this example was already disabled.
You could even set multiple values if you were so inclined. You’d just need to know the value of the settings combined or run multiple -bOrs.
This is all well and good if you want to turn ON a setting, but what if you want to turn OFF a setting?!
Enter “Bitwise NOT”, from below the stage.
We’re -bNot Getting the -bAnd back together
Remember that OR enables any bit value that has a value of 1 on either side of the comparison. AND on the other hand requires both to be set to 1 to return true. So if we think this out a bit we know that we just have to set a 0 for the setting we want to disable and set everything else as 1. Which is less than ideal because now we have to calculate the value of everything ON except the value we want to turn off.
Getting the band back together is never as easy as when you first started writing music together.
Bitwise NOT solves this issue. We just pass it our value and it flips all the bits just like a “-not” operator in PowerShell. 1s become 0s and 0s become 1s.
So now we just need to bAnd the bNot (I apologize to my mobile users in advance - I only did 32-bits to ease some of the pain).
0000 0000 0000 0000 0000 0000 0000 1101 (Decimal 13) 1111 1111 1111 1111 1111 1111 1111 1011 (Decimal 4294967291 - which is the -bNOT of 0100 or Decimal 4) --------------------------------------- -bAND 0000 0000 0000 0000 0000 0000 0000 1001 (Decimal 9) Represented in the PowerShell command: 13 -bAnd (-bnot 4)
Now you are thinking back to yourself about all those VBScripts you TOTALLY wrote yourself that had a “const” value defined at the top and you finally understand what the deal was with all those weird hex numbers.
While I’m sure there are way more informative posts on bitwise operations I hope this was at least somewhat informative and at least mildly entertaining to you. I’m not sure that you will ever find a true need for bitwise operations in your day to day hustle, but if you do and you found this post useful - drop me a line in the comments below.
And as always, happy admining!