[int]$PowerShellSkills++

After reading this post from Jeffrey Hicks about  how he found an old script and describes how he would have solved the same task today, I decided to do the same thing with one of my older scripts.

When I had just started learning PowerShell I had a need to map out free space on a large collection of servers, and not wanting to do this manually I of course created a script to help me out. I remember I was immensely proud of my self when I was finished with it, having created a re-usable script with help text and all. Looking back at it now, I see that I manage to break almost all best-practices regarding how to write PowerShell code, but we all have to start some place right?

Here is the original script I created back in 2008:

# ============================ #
# Disk Space Info (dsi) - V1.1 # 
#                              #
# 2008 - Øyvind Kallstad       #
# ============================ #


$wmiQuery = "SELECT SystemName,Caption,VolumeName,Size,Freespace FROM win32_logicaldisk WHERE DriveType=3"
$sortBy = "% Free"
$help = @"

USAGE:
    dsi.ps1 [-? | -help | -list [list.txt] | -remote [machine name] | 
         -sortname | -sort%]

Options:
    [no option]  Lists disk information for local machine
    -list        Lists disk information for all servers in the textfile
    -remote      Lists disk information for the remote machine specified
    -sortname    Sorts the output by the SystemName column
    -sort%       Sorts the output by the % Free column
    -help        This help message
    -?           This help message

"@

if ($args) {
  switch ($args) {
    "-help" {$help}
    "-?" {$help}
    "-list" {$wmi = gwmi -ErrorAction silentlycontinue -ErrorVariable err -query $wmiquery -computer (gc $args[1])}
    "-remote" {$wmi = gwmi -ErrorAction silentlycontinue -ErrorVariable err -query $wmiQuery -computer $args[1]}
    "-sortName" {$sortBy = "SystemName"}
    "-sort%" {$sortBy = "% Free"}
  }

}ELSE{

  $wmi = gwmi -ErrorAction silentlycontinue -ErrorVariable err -query $wmiQuery

}

$wmi | Select-Object SystemName,Caption,VolumeName,@{Name="Size(GB)"; Expression={"{0:N2}" -f ($_.Size/1GB)}},@{Name="Freespace(GB)"; Expression={"{0:N2}" -f ($_.Freespace/1GB)}}, @{n="% Free";e={"{0:P2}" -f ([long]$_.FreeSpace/[long]$_.Size)}} | sort $sortBy | format-table -autosize

if (!$args) {

if ($err) {write-host "There were " $err.count "error(s)"}

}

Looking at it now, I see that I’m almost doing something right, by returning a WMI object, just such a shame I’m ruining it by piping it through Format-Table at the end. I remember I was especially proud of the custom expressions in Select-Object (having googled an example).

So how would I have created this today? Something like this:

function Get-DiskInfo {
    [CmdletBinding()]
    param (
        [Parameter(ValueFromPipeline = $true, ValueFromPipelinebyPropertyName = $true)]
        [string[]] $ComputerName = $env:COMPUTERNAME
    )

    Process {
        foreach ($computer in $ComputerName) {
            try {
                Write-Output (Get-WmiObject -Query 'SELECT SystemName,Caption,VolumeName,Size,Freespace FROM Win32_LogicalDisk WHERE DriveType=3' -ComputerName $ComputerName | Select-Object SystemName,Caption,VolumeName,@{Name="Size(GB)"; Expression={"{0:N2}" -f ($_.Size/1GB)}},@{Name='Freespace(GB)'; Expression={"{0:N2}" -f ($_.Freespace/1GB)}}, @{n='% Free';e={"{0:P2}" -f ([long]$_.FreeSpace/[long]$_.Size)}})
            }
            catch {
                Write-Warning $_.Exception.Message
            }
        }
    }
}

The cool thing about this is that except for the ComputerName parameter, all my “old” parameters are handled by using Get-Help, Get-Content, Sort-Object and Format-Table. All this is possible because I’m outputting an object and handling the pipeline properly. I haven’t implemented comment based help in this example, but doing so would of course make Get-Help even more usable.

4 comments

    1. True, and a lot more I hope. But it’s funny.. the more I think I know about PowerShell, the more I realise that there is so much I don’t know! Exiting! 🙂

      Like

  1. I still use my first script to this day but I really don’t like looking at the code. It works like a charm to propagate ssl certificates to remote servers but it sure is ugly. Today, I would simply create x509Certificate and X509CertificateStore WMI objects to load the certificate and import it to the remote server. I still have not found a more elegant way to guarantee if its a Root, Intermediate or Leaf cert other than checking cert extensions for a specific OID, creating the Chain object and checking the chain status. However, typically I find that if the subject matches the issuer… you can bet its a root “most” of the time. There is proprietery information in the code otherwise I’d post it here (Also its embarrassingly ugly).

    Like

    1. Yeah, well.. if it works, it works, right? 🙂 The script I posted above worked a charm for me when I needed it, and at the end of the day, that is the most important thing. I always say to people who ask me for help in scripting that the first task is always to write something that works!

      Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s