Bookmark and Share

Microsoft Scripting Guy Ed Wilson here. Our alarm clock died a slow, but rather painless death. All of a sudden, it began to lose track of time. It would forget to wake us up in the morning, and worst of all, it would at times just randomly display time from different time zones and even alternate universes. At last, it was time to bid it a fond farewell. The demise of the alarm clock was not a major inconvenience, because the Scripting Wife and I actually set four alarms each morning. I have an alarm set on my Windows Mobile Smart phone, the Scripting Wife has one set on her Windows Mobile Smart phone, there is a windup backup alarm, and lastly the battery-backed electric alarm clock about whom we were previously speaking. You may think I am paranoid, but I call it just being prudent. A windup, backup alarm clock is of little use if you forget to wind it up. An electric alarm clock is of no use if the battery runs down and the electricity goes off. A Windows Mobile Smart phone is no good if you forget to recharge it or leave it in your computer bag downstairs. Therefore, with multiple redundant alarm systems in place, we are pretty much assured of avoiding the potentially embarrassing “I overslept” situation.

Anyway, trying out a new electric alarm clock is always a bit of a surprise that is sometimes pleasant, sometimes not. This morning was one of the “not” occasions. I am not sure where the Scripting Wife obtained the new alarm clock, but when it went off this morning, the results were alarming! (I’ll be here all week. Try the veal.) It is the loudest, most obnoxious sound I have ever heard, excepting the drill sergeant banging on a metal garbage can at oh dark thirty. I wonder if anyone has ever suffered a heart attack from one of these alarm clocks. Oh, well.

While I lingered over a pot of English Breakfast tea, I focused on something I had been wanting look at for a long time—the concept of enumerations. I have used enumerations numerous times in the scripts I have written for the Hey, Scripting Guy! posts, particularly in connection with the scripts I have written about automating Microsoft Word, Microsoft Excel, Microsoft PowerPoint, and Microsoft Outlook. Rather than simply hardcoding a numeric value into a method call, I create an instance of the enumeration, and then use the enumeration property names in the script. This promotes readability, and points the way to successfully modifying the script to accomplish other purposes because one can refer to the documentation on MSDN.

What if I want to create an enumeration for use in my Windows PowerShell scripts? How would I go about accomplishing that? One could always store the values in a hash table, and use the contains method to check for values, as shown here:

PS C:\> $hash = @{"a" = 5; "b" = 7}
PS C:\> $hash.Contains("b")
True
PS C:\>

A better approach would be to create a real instance of the System.Enum .NET Framework class. There is no direct way to do this, but because Windows PowerShell 2.0 has the Add-Type cmdlet that allows me to use C# code, I can create my own enumeration. This is not very difficult to do. Understanding how to use the enumeration after it is created is more of a challenge, but creating the enumeration is simple. The Create-FruitEnum.ps1 script illustrates the technique to create an enumeration. The complete script is shown here.

Create-FruitEnum.ps1

$enum = "
namespace myspace
{
public enum fruit
{
apple = 29, pear = 30, kiwi = 31
}
}
"
Add-Type -TypeDefinition $enum -Language CSharpVersion3

The key to using the Add-Type cmdlet to create the enumeration is to use the –TypeDefinition parameter. You also need to specify the language. Permissible language values are CSharp, CSharpVersion3, VisualBasic, and Jscript.

The TypeDefinition is a string that contains the code that will be used to create the enumeration. The first thing that needs to be done is to specify a namespace that will contain the enumeration. Namespaces are used to group similar classes and enumerations in the .NET Framework. If I were creating a number of enumerations that I would use in a project, I would ensure they were all stored in the same namespace. For this example, I am using a rather silly namespace called myspace. This namespace does not exist, I would imagine, before running this script. Keep in mind that C# is case sensitive. The command is namespace, and the name of the namespace to create is myspace.

After the namespace declaration, the enum command is used to create the enumeration. Because I want to be able to use the enumeration in other places, I use the public keyword to make it available. After the public command, the enum command is followed by the name of the enumeration to create. Because my enumeration will consist of several different types of fruit, I call it Fruit.

The last step involved in creating an enumeration is to list each enumeration and its associated value. Even though each different kind of fruit is a string, you do not place quotation marks around the name of the fruit. That will cause an error to be generated. Therefore, I have the name of a type of fruit, an equal sign, and the value I wish to assign to the enumeration.

When I run the code, nothing is displayed, which is demonstrated in the following image.

Image of nothing shown when script is run

The question may arise: How can I tell if it worked or not?

One of the easiest ways is to put the enumeration namespace and name inside square brackets and press ENTER. This is done in the command pane. If the enumeration has been created properly, you will see the output shown here:

PS C:\Users\edwils> [myspace.fruit]
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True fruit System.Enum

If you want to see which enumeration values have been created, you can use the GetValues static method from the system.enum .NET Framework class. This is shown here:

PS C:\Users\edwils> [enum]::GetValues([myspace.fruit])
apple
pear
kiwi

If you wish to retrieve a specific value from the fruit enumeration, you access the properties as if they were static properties. This is shown here:

PS C:\Users\edwils> [myspace.fruit]::pear
pear

As you can see, the results are not too terribly exciting. What is cool, however, is being able to retrieve the numeric value we assigned to the enumeration property when we created the fruit enumeration. To do this, use the value__ (that is a double underscore trailing the word value) property shown here:

PS C:\Users\edwils> [myspace.fruit]::pear.value__
30

 

It looks like it is going to be a nice day here in Charlotte. I think I will head out to the woodworking shop for a while. I will catch you later. Have a great day.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson and Craig Liebendorfer, Scripting Guys