<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Media And Microcode : System.Collections.Hashtable</title><link>http://blogs.msdn.com/mediaandmicrocode/archive/tags/System.Collections.Hashtable/default.aspx</link><description>Tags: System.Collections.Hashtable</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Microcode: PowerShell Scripting Tricks: More Joy of Hashtables (with Get-HashtableAsObject)</title><link>http://blogs.msdn.com/mediaandmicrocode/archive/2008/11/30/microcode-powershell-scripting-tricks-more-joy-of-hashtables-with-get-hashtableasobject.aspx</link><pubDate>Sun, 30 Nov 2008 05:10:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9156852</guid><dc:creator>JamesBrundage</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/mediaandmicrocode/comments/9156852.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mediaandmicrocode/commentrss.aspx?PostID=9156852</wfw:commentRss><description>&lt;p&gt;I recently did two different &amp;quot;in depth&amp;quot; posts.&amp;#160; One on &lt;a href="http://blogs.msdn.com/mediaandmicrocode/archive/2008/11/27/microcode-powershell-scripting-tricks-the-joy-of-using-hashtables-with-windows-powershell.aspx"&gt;The Joy Of Hashtables&lt;/a&gt; and another on &lt;a href="http://blogs.msdn.com/mediaandmicrocode/archive/2008/11/26/microcode-powershell-scripting-tricks-select-object-note-properties-vs-add-member-script-properties.aspx"&gt;Select-Object versus Add-Member&lt;/a&gt;.&amp;#160; At the end of Select-Object vs Add-Member, I hinted at more convenient ways to write objects that used Script Properties.&amp;#160; Script Properties are particularly useful because, unlike Note Properties, they are evaluated when they are requested.&amp;#160; This means that PowerShell scripts that use script properties will often be faster than those using note properties.&amp;#160; Sadly, they're kind of clunky to add.&amp;#160; A script property will normally look like:&lt;/p&gt; &lt;i&gt;   &lt;blockquote&gt;     &lt;pre&gt;New-Object Object | Add-Member ScriptProperty Foo { Get-Random } -passThru&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/i&gt;

&lt;p&gt;This gets pretty ugly, pretty fast.&lt;/p&gt;

&lt;p&gt;Luckily, the post on hashtables gives us a good way out of this problem.&amp;#160; Hashtables look fairly clean in PowerShell scripts, and, with a little bit of work, you can easily turn a hashtable into an object. Here's the Get-HashtableAsObject function.&lt;/p&gt;

&lt;p&gt;In case you're curious, the comments inside of the function aren't just there for fun. They're an example of script-embedded help (which will not be out until CTP3). Once script-embedded Help is there, you can write help content for a function with just what's in the function below, and you'll be able to Get-Help on your function just like any other command.&lt;/p&gt;
&lt;i&gt;
  &lt;blockquote&gt;
    &lt;pre&gt;function Get-HashtableAsObject([Hashtable]$hashtable)
{  
    #.Synopsis
    #    Turns a Hashtable into a PowerShell object
    #.Description
    #    Creates a new object from a hashtable.
    #.Example
    #    # Creates a new object with a property foo and the value bar
    #    Get-HashtableAsObject @{&amp;quot;Foo&amp;quot;=&amp;quot;Bar&amp;quot;}
    #.Example
    #    # Creates a new object with a property Random and a value
    #    # that is generated each time the property is retreived
    #    Get-HashtableAsObject @{&amp;quot;Random&amp;quot; = { Get-Random }}
    #.Example
    #    # Creates a new object from a hashtable with nested hashtables
    #    Get-HashtableAsObject @{&amp;quot;Foo&amp;quot; = @{&amp;quot;Random&amp;quot; = {Get-Random}}} 
    process {       
        $outputObject = New-Object Object
        if ($hashtable -and $hashtable.Count) {
            $hashtable.GetEnumerator() | Foreach-Object {
                if ($_.Value -is [ScriptBlock]) {
                    $outputObject = $outputObject | 
                        Add-Member ScriptProperty $_.Key $_.Value -passThru
                } else {
                    if ($_.Value -is [Hashtable]) {
                        $outputObject = $outputObject | 
                            Add-Member NoteProperty $_.Key (Get-HashtableAsObject $_.Value) -passThru
                    } else {                    
                        $outputObject = $outputObject | 
                            Add-Member NoteProperty $_.Key $_.Value -passThru
                    }
                }                
            }
        }
        $outputObject
    }
}&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/i&gt;

&lt;p&gt;Let's check out a few practical examples of Get-HashtableAsObject:&lt;/p&gt;

&lt;p&gt;Check out how we can use Get-HashtableAsObject to create a random card&lt;/p&gt;
&lt;i&gt;
  &lt;blockquote&gt;
    &lt;pre&gt;$card = Get-HashtableAsObject @{
    Card = {2..9 + &amp;quot;Jack&amp;quot;, &amp;quot;Queen&amp;quot;, &amp;quot;King&amp;quot;, &amp;quot;Ace&amp;quot; | Get-Random}
    Suit = {&amp;quot;Clubs&amp;quot;, &amp;quot;Hearts&amp;quot;, &amp;quot;Diamonds&amp;quot;, &amp;quot;Spades&amp;quot; | Get-Random}
}
$card
$card
$card&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/i&gt;

&lt;p&gt;Notice that each time I output $card, the Card and Suit change. This is because the script property is being evaluated each time it is read. Essentially, it's shuffling every card. Cool, right?&lt;/p&gt;

&lt;p&gt;The last post introduced you to PowerShell's ability to add hashtables together to merge them.&amp;#160; Check out how we can use this to combine an object that generates user information and an object that generates system information.&lt;/p&gt;
&lt;i&gt;
  &lt;blockquote&gt;
    &lt;pre&gt;$userInfo = @{
    LocalUsers = {Get-WmiObject &amp;quot;Win32_UserAccount WHERE LocalAccount='True'&amp;quot;}
    LoggedOnUsers = {Get-WmiObject &amp;quot;Win32_LoggedOnUser&amp;quot; }    
}

$systemInfo = @{
    Memory = {Get-WmiObject Win32_PhysicalMemory}
    Drives = {Get-WmiObject Win32_LogicalDisk}
}

$liveUserInfo = Get-HashtableAsObject $userInfo
$liveSystemInfo = Get-HashtableAsObject $systemInfo
$allInfo = Get-HashtableAsObject ($userInfo + $systemInfo)

$liveUserInfo.LocalUsers
$allInfo.Drives&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/i&gt;

&lt;p&gt;This trick is particularly convenient for quickly joining together chunks of logic from different scripts. For instance, if I wanted to add a property the $userInfo object that kicked off all users who had been logged on for over a period of time, I'd simply add another hashtable to the user info to accomplish this task. For those much more in tune with object-oriented programming, what this essentially gives me is the ability to inherit from an objects defined this way in PowerShell, without the joy of overloading.&amp;#160; Faking overloading is considerably more complicated, so we'll save that one for another day, but I hope that the tricks contained within this post help you write more robust scripts.&lt;/p&gt;

&lt;p&gt;Hope this helps,&lt;/p&gt;

&lt;p&gt;James Brundage [MSFT]&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9156852" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/PowerShell/default.aspx">PowerShell</category><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/Microcode/default.aspx">Microcode</category><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/Add-Member/default.aspx">Add-Member</category><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/System.Collections.Hashtable/default.aspx">System.Collections.Hashtable</category><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/Get-HashtableAsObject/default.aspx">Get-HashtableAsObject</category></item><item><title>Microcode: PowerShell Scripting Tricks: The Joy of using Hashtables with Windows PowerShell</title><link>http://blogs.msdn.com/mediaandmicrocode/archive/2008/11/27/microcode-powershell-scripting-tricks-the-joy-of-using-hashtables-with-windows-powershell.aspx</link><pubDate>Thu, 27 Nov 2008 10:01:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9145970</guid><dc:creator>JamesBrundage</dc:creator><slash:comments>4</slash:comments><comments>http://blogs.msdn.com/mediaandmicrocode/comments/9145970.aspx</comments><wfw:commentRss>http://blogs.msdn.com/mediaandmicrocode/commentrss.aspx?PostID=9145970</wfw:commentRss><description>&lt;p&gt;PowerShell is full of nice little touches.&amp;nbsp; While some of these touches are easy to run across, like Get-Command and Get-Help, there are also a lot of little ones that are very small changes that make working with some parts of PowerShell (and .NET) a whole lot easier.&amp;nbsp; One area that's got a lot of little goodness, but that probably isn't as well-known, is the joy of using a Hashtable in PowerShell.&lt;/p&gt; &lt;p&gt;For the uninitiated, you can create an instance of System.Collections.Hashtable in Windows PowerShell by the simple shorthand @{Key=Value}.&amp;nbsp; This offers a way you can express rather complicated data in a PowerShell script while keeping clean looking scripts.&amp;nbsp; For instance, here's how some moderately complex personal information might look as a hashtable. &lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;$person = @{
    First = "James"
    Last = "Brundage"
    Address = @{
        City = "Seattle"
        State = "Washington"
        Zip = 98102
        Street = "0 Way I Am Putting This On a Blog" 
    }
    Occupation = @{
        Industry = "Information Technology"
        Title="Software Developer In Test"
        Company="Microsoft Corporation"
    }
}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now that we've covered the basics, lets get to the cool tricks.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Did you know? in PowerShell + adds Hashtables together.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Watch how you use this on $person to make a new key:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$person+=@{"FullName" = "$($person.First) $($person.Last)"}&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;/pre&gt;
&lt;p&gt;Nifty, right?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Did you know?&amp;nbsp; You can use the . operator to get or set a Hashtable entry.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$person.FullName&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Since you can peek at values with a ., you can do a quick check to fill in information that might be missing from the hashtable.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Check out how to fill in the missing information from John Doe&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$otherPerson = @{
    First = "John"
    Last = "Doe"    
}

$people = $person, $otherPerson

$people = $people | Foreach-Object {
    $p = $_ + @{"FullName" = "$($_.First) $($_.Last)"}    
    if (-not $p.Address) {
        $p.Address = "Unknown"
    }
    if (-not $p.Occupation) {
        $p.Occupation = "Unknown"
    }
    $p
}
$people
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;You can also access nested hashtables this way, which lets you group complex data.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Watch how to use this to create a new variable, $westCoastPeople:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$westCoastPeople = $people |
    Where-Object {"Washington", "Alaska", "Hawaii", "Oregon", "California" -contains $_.Address.State }&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;You can also use Group-Object to group by different properties.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$people | Group-Object {$_.Address.City, $_.Address.State} 
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;If you need to walk through each item in a hashtable, then you can use .GetEnumerator() to walk the entries.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$person.GetEnumerator() | Foreach-Object {    
    $_.Key
    "-"
    $_.Value | Out-String
}
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;You can't remove an item while you're enumerating it, but by wrapping the enumerator in @(), you actually get a snapshot of collection and then you're free to modify it as you see fit.&lt;/p&gt;
&lt;p&gt;Check out how you can use this to clear out any field that has "Unknown" in it.&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$people | Foreach-Object {
    $p = $_
    @($p.GetEnumerator()) | Where-Object {            
        ($_.Value | Out-String) -like "*Unknown*"
    } | Foreach-Object {
        $p.Remove($_.Key)
    }
}

$people
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;As you can see, several nooks and crannies of how PowerShell works with .NET are quite useful, and make working with some objects in PowerShell incredibly nice.&amp;nbsp; I hope you've had some fun with hashtables, and I hope I can shed some more light on fun with different .NET types in the future.&lt;/p&gt;
&lt;p&gt;Hope this helps,&lt;/p&gt;
&lt;p&gt;James Brundage [MSFT]&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9145970" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/PowerShell/default.aspx">PowerShell</category><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/Microcode/default.aspx">Microcode</category><category domain="http://blogs.msdn.com/mediaandmicrocode/archive/tags/System.Collections.Hashtable/default.aspx">System.Collections.Hashtable</category></item></channel></rss>