November 23rd, 2008

PoshBoard and ConvertTo-HashTable

PowerShell Team
PowerShell Team

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

Author

PowerShell Team
PowerShell Team

PowerShell is a task-based command-line shell and scripting language built on .NET. PowerShell helps system administrators and power-users rapidly automate tasks that manage operating systems (Linux, macOS, and Windows) and processes.

0 comments

Discussion are closed.