Bookmark and Share


Microsoft Scripting Guy Ed Wilson here. The Scripting Wife and I are on the road again. She is driving, and I am playing around with Windows PowerShell enumerations. Teresa made friends with a couple we met in the concierge lounge of our hotel in Lisbon while I was teaching a month’s worth of Windows PowerShell workshops. She has remained friends with them ever since, and this weekend we are meeting in Chattanooga, Tennessee, to see the Glen Miller Orchestra. The good thing about having a power adapter in the car is I can write scripts during the entire journey—from that perspective there is no difference from being at home or on the road. Well, there is one thing that is different: I do not have good Internet access from the car. It is true I can use my Windows Mobile device to search the Internet, and if I tried, I bet I could make it emulate a modem for my laptop, but that is more trouble than it is worth. The cool thing is that Windows PowerShell is largely self-documenting, which means I can use the Get-Member cmdlet to discover methods and properties of objects.

I have been playing around with enumerations in Windows PowerShell since last weekend, and I decided to see how I would use one in a script. Using the myspace.fruit enumeration I created last week, I can use an enumeration value to branch out to different parts of a script. I can also check to see if the enumeration is legitimate or not. The Get-FruitEnumDemo_enumContains.ps1 script illustrates this technique. After the myspace.fruit enumeration has been loaded into memory, the Get-Fruit function accepts an enumeration value. The contains operator is used to see if the enumeration exists; a switch statement performs different actions based upon the enumeration value. If the enumeration does not exist, a message is displayed that states the enumeration is not valid and displays the permissible values. The Get-FruitEnumDemo_enumContains.ps1 script is shown here.

Get-FruitEnumDemo_enumContains.ps1

Function Get-Fruit
{
Param($enumvalue)
if([enum]::Getvalues([myspace.fruit]) -contains $enumValue)
{
switch ([enum]::parse([type]"myspace.fruit",$enumValue))
{
([myspace.fruit]::apple) { "Apples are good" }
([myspace.fruit]::pear) { "Pears are yummy" }
([myspace.fruit]::kiwi) { "Kiwis are great" }
} #end switch
} # end if
else {
"Your enumeration is invalid. Please use one of the following values:"
[enum]::getValues([myspace.fruit])
}
} #end function
Get-Fruit "plum"

A string is passed to the Get-Fruit function via the $enumvalue parameter. An if statement first retrieves all permissible values for the enumeration, and then uses the contains operator to see if the supplied value exists. This is shown here:

Function Get-Fruit
{
Param($enumvalue)
if([enum]::Getvalues([myspace.fruit]) -contains $enumValue)
{

The switch statement evaluates an actual enumeration value, but a string was passed to the function. To correct this, the parse static method from the system.enum .NET Framework class is used. It accepts two arguments: the first is an enum and the second is an enum value. The string myspace.fruit is cast into an enum (or a type) by using the [type] type constraint:

[enum]::parse([type]"myspace.fruit",$enumValue)

The parse method translates the string into an actual instance of the enumeration. This is shown here:

PS C:\Users\ed.NWTRADERS> [enum]::parse([type]"myspace.fruit","pear")
pear
PS C:\Users\ed.NWTRADERS> [enum]::parse([type]"myspace.fruit","pear").Gettype()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True fruit System.Enum

If you supply a value that is not part of the enumeration, the parse method throws an error as shown here:

PS C:\Users\ed.NWTRADERS> [enum]::parse([type]"myspace.fruit","peach")
Exception calling "Parse" with "2" argument(s): "Requested value 'peach' was not found."
At line:1 char:14
+ [enum]::parse <<<< ([type]"myspace.fruit","peach")
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException

That situation (parse throwing an error) should never occur because the contains operator used to determine the supplied value is actually part of the enumeration. After the parse method has converted the string into an instance of the enumeration, the switch statement is smart enough to match it. When a match is found, the appropriate script block is called. In this demo, switch displays a string, but this could be a decision matrix that calls other functions or Windows PowerShell cmdlets:

{
([myspace.fruit]::apple) { "Apples are good" }
([myspace.fruit]::pear) { "Pears are yummy" }
([myspace.fruit]::kiwi) { "Kiwis are great" }
} #end switch

If the enumeration value is not found, a message is displayed that lists the permissible enumeration values. This is shown here:

else {
"Your enumeration is invalid. Please use one of the following values:"
[enum]::getValues([myspace.fruit])
}

When the script runs and an invalid enumeration is submitted, the following output is displayed.

Image of output displayed when invalid enumeration is submitted

 

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