PoshBoard and ConvertTo-HashTable

PoshBoard and ConvertTo-HashTable

  • Comments 5

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

Leave a Comment
  • Please add 5 and 3 and type the answer here:
  • Post
  • PingBack from http://www.alvinashcraft.com/2008/11/24/dew-drop-november-24-2008/

  • 1. How do you get the pipe line to execute correctly without specifying the path to ConvertTo-Hashtable? I get the error "convertto-hashtable is not recognized as a cmdlet, function, operable program, or script file.". I have to specify the path or ./ to avoid the error.

    #2. I also get the error "The operation '[System.UInt64] - [System.UInt64]' is not defined.

    At line:1 char:96

    + $ht = gwmi win32_logicaldisk -filter "drivetype=3" | ./convertto-hashtable deviceid { $_.size -  <<<< $_.freespace }

    The operation '[System.UInt64] - [System.UInt64]' is not defined."

    It works if you add back the division by 1KB to both the size and freespace fields

  • James, you can get around the path problem by using Jeffrey's code as a function like:

    function ConvertTo_HashTable {

    <insert Jeffrey's code here>

    }

    The conversion problem can be fixed by casting the variables as doubles:

    {[double]$_.size - [double]$_.freeSpace}

    Jeffrey, thanks for the code! I have been using the foreach loop method to populate hashes. Using your code will be a much more elegant solution.

  • great information thanks this def helps

  • Hi,

    thank you for theses advices : for sure, this dramatically simplify the stuff !

    I'll implement it this way in the coming version of Poshboard.

    Antoine

Page 1 of 1 (5 items)