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 = @"

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

    [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"}


  $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 {
    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.


    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! 🙂


  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).


    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!


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 )

Google+ photo

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

Connecting to %s