PoshBoard and ConvertTo-HashTable

I’m currently watching an cool video of PoshBoard a PowerShell based Web Portal by Pilosite available on CodePlex.   It looks great. 


In the middle of the video I noticed the following script he uses to populate one of the controls on the dashboard:


$ht = @{ }
$objDrives = gwmi –class “Win32_logicalDisk” –Namespace “root\cimv2” |where {$_.DriveType -eq 3 }
foreach ($ObjDisk in $objDrives)
{
    $size = $objDisk.size / 1024
    $freespace = $objDisk.FreeSpace / 1024
    $IntUsed = ($size – $freeSpace) * 1024
    $ht.Add($objDisk.DeviceId, $IntUsed)
}


This is perfectly fine code but I noticed a couple opportunities for improvement:



  1. You don’t need to use quotes in:  “Win32_logicalDisk”  or “root\cimv2”

  2. The default namespace for gwmi is root\cimv2 so it it is redundant

  3. Gwmi supports –FILTER which can be dramatically more efficient so it is worth learning it’s different syntax and using it when you can

  4. CLASS can be a positional parameter so you don’t need to say –CLASS.

Those observations allow us to transform


     $objDrives = gwmi –class “Win32_logicalDisk” –Namespace “root\cimv2” |where {$_.DriveType -eq 3 }


into


    $objDrives = gwmi Win32_logicalDisk –Filter “DriveType = 3”


Next I noticed that it was using a foreach loop to create a hashtable.  I’ve seen lots of code like this and in talking to a lot of new users, I’ve come the the conclusion that there are a set of beginner users that have a difficult time getting their heads around control structures (e.g. if/elseif/else, for, foreach, while, do/until).  These folks seem to do just fine with commands and pipelines so I’m on the lookout for ways to make control structures option.  In the spirit, I wrote ConvertTo-HashTable.ps1 :


# ConvertTo-hashTable.ps1
#   
param(
[string] 
$key,


$value
)
Begin
{
    $hash = @{}
    $Script = $false
    if ($value -is [ScriptBlock])
    {
        $Script = $true
    }
}
Process
{
    $thisKey = $_.$Key
    if ($script)
    {
        $hash.$thisKey = & $Value        
    }else
    {
        $hash.$thisKey = $_.$Value
    }
}
End
{
    Write-Output $hash
}


Once you have this (and you notice that you can get rid of the multiplying and dividing by 1024), we can transform this:


$ht = @{ }
$objDrives = gwmi –class “Win32_logicalDisk” –Namespace “root\cimv2” |where {$_.DriveType -eq 3 }
foreach ($ObjDisk in $objDrives)
{
    $size = $objDisk.size / 1024
    $freespace = $objDisk.FreeSpace / 1024
    $IntUsed = ($size – $freeSpace) * 1024
    $ht.Add($objDisk.DeviceId, $IntUsed)
}


into this:


$ht = gwmi Win32_logicalDisk –Filter “DriveType = 3” | ConvertTo-HashTable DeviceId {$_.size – $_.freeSpace}


That looks pretty readable to me.


BTW – here is the video




PowerShell Dashboard Web Portal Presentation from pilosite on Vimeo.

Enjoy!


Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx