PowerShell Hash Tables that Contain Keywords...hmm...

PowerShell Hash Tables that Contain Keywords...hmm...

  • Comments 3
  • Likes

Summary: Microsoft Scripting Guy, Ed Wilson, talks about dealing with Windows PowerShell hash tables that contain keywords. Dude!

Hey, Scripting Guy! Question Hey, Scripting Guy! I have a problem in that I want to create a hash table from an array. This is easy enough to do, but if the array contains keywords, then everything goes pear shaped. Any ideas?

—GP

Hey, Scripting Guy! Answer Hello GP,

Microsoft Scripting Guy, Ed Wilson, is here. Things are certainly  becoming exciting around here. The Scripting Wife and I have been busy planning for TechEd North America in New Orleans and TechEd Europe in Madrid. As it turns out, we will have a Scripting Guys booth in both New Orleans and Madrid. In addition, we are sharing our booth with the folks from PowerShell.org; so, that means that Windows PowerShell people like Don Jones will be there. I am also going to be working with the Windows PowerShell team on a couple of instructor lead labs that (to be quite honest) will absolutely knock your socks off —they are that cool. More details to follow.

Creating a hash table that contains keywords

Well GP, I have never actually run across your problem before. This is because I avoid using Windows PowerShell keywords. I refer to the Help topic, about_Language_Keywords, from time to time to refresh my mind when it comes to reserved keywords.

Note   As an aside, I do the same thing for automatic variables. For more information, see about_Automatic_Variables in the Script Center. 

Here is the easy way to bring up the about_Language_Keywords Help topic:

help -Category helpfile -Name *keyword*           

So, this is all on the preventive side of things. To experiment with this, the first thing I do is create an array that contains a few keywords—in addition to other words. I then use the ForEach command to add the items in the array to a hash table. This technique is shown here:

PS C:\> $a = "key","keys","property","properties","red","blue","green"

PS C:\> $h = @{}

PS C:\> foreach ($wd in $a) {$h[$wd] = $true}

If I look at the hash table that is contained in the $h variable, I see the following:

PS C:\> $h

 

Name                           Value

----                           -----

red                            True

property                       True

green                          True

keys                           True

properties                     True

blue                           True

key                            True

So far, so good.  But suppose I want to look at the properties or the keys of my hash table. I try the following:

PS C:\> $h.Keys

True

PS C:\> $h.key

True

PS C:\> $h.property

True

PS C:\> $h.properties

True

So I am wondering what the properties really are for this hash table. I can find out by using the Get-Member command as shown here.

PS C:\> Get-Member -InputObject $h -MemberType Properties

 

   TypeName: System.Collections.Hashtable

 

Name           MemberType Definition

----           ---------- ----------

Count          Property   int Count {get;}

IsFixedSize    Property   bool IsFixedSize {get;}

IsReadOnly     Property   bool IsReadOnly {get;}

IsSynchronized Property   bool IsSynchronized {get;}

Keys           Property   System.Collections.ICollection Keys {get;}

SyncRoot       Property   System.Object SyncRoot {get;}

Values         Property   System.Collections.ICollection Values {get;}

There really is a property called Keys, and I really cannot seem to access it. So what do I do?

I imagine that I will take a look at the base Windows PowerShell object. To do this, I use the PSBase property. All Windows PowerShell objects have a base object, but most of the time, it is not necessary to fool with it. Here, however, I suspect that I will be able to get past the keys keys kind of thing. Here is the base object:

PS C:\> $h.psbase

IsReadOnly     : False

IsFixedSize    : False

IsSynchronized : False

Keys           : {red, property, green, keys...}

Values         : {True, True, True, True...}

SyncRoot       : System.Object

Count          : 7

Now, I see there is a Keys property on the base object. So I attempt to access it. Here is how I do it:

PS C:\> $h.psbase.keys

red

property

green

keys

properties

blue

key

GP, that is all there is to using PSBase when dealing with hash tables. By the way, I tested this on Windows PowerShell 2.0 and on Windows PowerShell 3.0, so you should be safe to use this technique. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Just what i needed. Thx Ed

  • Using PSBase to get to the keys property of a hashtable is useful if there is an entry with that name, but I'm not sure where keywords play into this.  From the about_language_keywords topic, "keys" isn't a keyword.

    All of these techniques for constructing hash tables using keywords (I'm using foreach and if) seem to work fine.

    $hash=@{}

    $hash.foreach='Hello'

    $hash.foreach

    $hash=@{foreach='hello'}

    $hash.foreach

    $hash['if']='world'

    $hash.if

  • The issue here is not so much about keywords as it is about members in the hashtable colliding with properties on the hashtable class.  As well as PSBase (probably the best solution) you could use the "accessor" method for the property. For any property Foo, the accessor is get_Foo(). So to get the list of keys from a hashtable, you could do $h.get_keys()