Managing Bit Flags (Part 4)

by Mar 8, 2017

In PowerShell 5, the new support for enums makes dealing with bit values much easier as you’ve seen in previous tips. Even setting or clearing bits no longer requires cumbersome logical operators anymore.

Let’s first define an enum and make the decimal more manageable:

#requires -Version 5

[Flags()]
enum GardenPartyItems
{
    Chair = 0
    Table = 1
    Barbecue = 2
    Fridge = 4
    Candle = 8
    Knife = 16
}

$decimal = 11
[GardenPartyItems]$flags = $decimal
$flags

Now, the bits from any decimal can be easily converted to a list of garden party items:

 
PS C:\>  [GardenPartyItems]11
Table, Barbecue, Candle

PS C:\>  
 

Important: when you cast a decimal to an enumeration, always make sure that all bits are defined in your enum. If the decimal is too large and contains more bits than your enum, the conversion fails.

To add a new flag, try this:

 
PS C:\> $flags
Table, Barbecue, Candle

PS C:\> $flags += [GardenPartyItems]::Knife

PS C:\> $flags
Table, Barbecue, Candle, Knife

PS C:\>
 

To remove a flag, do this:

 
PS C:\> $flags
Table, Barbecue, Candle, Knife

PS C:\> $flags -= [GardenPartyItems]::Candle

PS C:\> $flags
Table, Barbecue, Knife

PS C:\>
 

However, this is not as straightforward as it seems. When you remove a flag that was set before, you are fine. But when you remove a flag that wasn’t there in the first place, you mess up your bit values:

 
PS C:\> $flags
Table, Barbecue, Candle

PS C:\> $flags -= [GardenPartyItems]::Candle

PS C:\> $flags
Table, Barbecue

PS C:\> $flags -= [GardenPartyItems]::Candle

PS C:\> $flags
-5

PS C:\>
 

So obviously PowerShell isn’t clever enough (yet) to use binary arithmetic automatically. To play safe, you’d still have to use binary operators. To remove flags, use -band and -bnot:

 
PS C:\> $flags
Table, Barbecue, Candle

PS C:\> $flags = $flags -band -bnot [GardenPartyItems]::Candle

PS C:\> $flags 
Table, Barbecue

PS C:\> $flags = $flags -band -bnot [GardenPartyItems]::Candle

PS C:\> $flags
Table, Barbecue

PS C:\>
 

And to set flags, use -bor:

 
PS C:\> $flags
Table, Barbecue, Candle

PS C:\> $flags = $flags -bor [GardenPartyItems]::Knife

PS C:\> $flags
Table, Barbecue, Candle, Knife

PS C:\> $flags = $flags -bor [GardenPartyItems]::Knife

PS C:\> $flags
Table, Barbecue, Candle, Knife

PS C:\>
 

In all of these operations, you were working with just a decimal:

 
PS C:\> [Int]$flags
19
 

Awesome, eh?

Twitter This Tip! ReTweet this Tip!