Executive Summary:
Here's a quick review of how bitmap values work and how you can use them with Windows Powershell for passing information between functions. You can use bitwise operators and masks to manipulate bitmap values.

The D.ps1 script described in "Emulating the Dir Command in PowerShell" relies on bitmap values for passing information between functions. A bitmap value is a concise way of storing a list of Boolean (i.e., true/false) values. You can think of a bitmap value as an array of bits rather than a discrete number. Each bit in the number is set to either 1 (enabled) or 0 (disabled). You can combine a bitmap value with a mask by using bitwise operators (in Windows PowerShell, these are -band, -bor, -bnot, and -bxor) so that you can read, set, clear, and toggle bits in the bitmap value. A mask is a number that represents the bit or bits you're interested in. Mask values are always powers of two.

File attributes are a good example of how the OS uses bitmap values. The following PowerShell command lists the .NET System.IO.FileAttributes enum and the associated mask value for each attribute:

\[Enum\]::GetValues(\[System.IO.FileAttributes\]) |
  select-object @\{"Name" = "Name"; "Expression" = \{$_\}\},
  @\{"Name" = "Value"; "Expression" = \{\[Int\] $_\}\} |
  format-table -auto

Figure A shows this command and its output.

From Figure A, we can see that a mask of 1 represents the read-only attribute, 2 (10 in binary) represents the hidden attribute, 4 (100 in binary) represents the system attribute, 16 (1000 in binary) represents the directory attribute, and so forth. You can combine multiple values with the -bor operator to create a multibit mask. For example, the mask 2 -bor 32 combines the hidden (2) and archive (32) attributes.

You can get a file's attributes by reading its Attributes property, which is really the .NET type System.IO.FileAttributes. If you cast the property as an integer by using \[Int\], you get the Attributes property's bitmap value. Consider the following example:

PS > $attrs = (get-item c:\test.txt).Attributes
PS > $attrs
ReadOnly, Archive
PS > \[Int\] $attrs
33

The first command retrieves c:\test.txt's attributes; the second command displays the $attrs variable, which PowerShell outputs as a list of attributes; and the third command displays the $attrs variable as an integer (i.e., its corresponding bitmap value).

PowerShell automatically converts the .NET values to integers in comparisons, which lets you use code such as the following:

PS > \[System.IO.FileAttributes\]::ReadOnly -eq 1
True
PS > \[System.IO.FileAttributes\]::Hidden -eq 2
True

The following formulas describe how to set and change the bits in a bitmap value:

  • Check to see if at least one bit is set: (bitmap -band mask) -ne 0
  • Check to see if all of the bits are set: (bitmap -band mask) -eq mask
  • Check to see if none of the bits are set: (bitmap -band mask) -eq 0
  • Set one or more bits: bitmap = bitmap -bor mask
  • Clear one or more bits: bitmap = bitmap -band (-bnot mask)
  • Toggle one or more bits: bitmap = bitmap -bxor mask

Using the $attrs variable from the previous example, we can use code such as the following:

($attrs -band 1) -ne 0 # True because the read-only bit is set
($attrs -band 2) -ne 0 # False because the hidden bit is not set
($attrs -band 32) -ne 0 # True because the archive attribute is set
($attrs -band (1 -bor 32)) -eq $attrs # True because both the
  read-only and archive bits are set

The D.ps1 script described in "Emulating the Dir Command in PowerShell" uses bitmap values and masks in its get-attributeflags and main functions, which you can see in the listing with that article.