Building Better Flagged Enums in PowerShell

Sometimes you need a good way to overload an array of options into a single value. Consider how an Enum created with Bitwise Operators can help.

Building Better Flagged Enums in PowerShell

Look, this isn’t a common thing. But sometimes you need it, and this post is to help you understand what’s going on. Time to dive in!

Enums and Flags

Do you already know what an enum in powershell is? Its like of like a cross between a class and a hashtable/keyed dict. Enums are great for STATIC conversion of strings to values for things like configuration options. Adding [System.Flags] to an enum allows you to set multiple values at once, kind of like overloading an array of enums into a single enum.

The reference doc shows how to add flags to your enum. Its like this:

[Flags()] enum <enum-name> {
    <label 0> [= 1]
    <label 1> [= 2]
    <label 2> [= 4]
    <label 3> [= 8]
    ...
}

To make a more practical example, imagine you wanted to store in a single field what services each server at work has. You could use a flagged enum to store all the possible combinations like so:

[Flags()] enum roles {
    none     = 0
    DC       = 1
    Files    = 2
    Printing = 4
    WSUS     = 8
}

You would assign it via: [roles]$roles = "dc","files" or similar. Accessing the $roles variable would output DC, Files to screen. And accessing the underlying value via $roles.Value__ would output 3. If you haven’t guessed: 1 + 2 = 3.

Note: The MS reference doc states that you MUST set the numbers to increasing by a factor of 2 for each item or else it won’t work. The doc doesn’t tell you that it will just silently fail to perform like you expect. :D

Leveraging Bitwise Operators

Bitwise operations involve shifting bits to the left or the right to increase or decrease a value using bit math. In PowerShell, bitwise operations are done via -shl and -shr (shift left and shift right).

Make the same representation for the roles enum using the -shl bitwise operator:

[Flags()] enum roles {
    none     = 0
    DC       = 1 -shl 0
    Files    = 1 -shl 1
    Printing = 1 -shl 2
    WSUS     = 1 -shl 3
}

Wrapping up

This post was inspired by the Discord API reference for adding Message Flags to Discord Interactions while I was writing a PowerShell Discord bot (that uses the C# DiscordDoorway).

When your code matches more closely to what others do, it makes your code more clear and more predictable. In that vein of being predictable, using flagged enums is one tool that you should use when needed, but please don’t add flagged enums to your code needlessly.