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.
Nice story. You also learned proper error handling and got rid of aliases.
LikeLike
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! 🙂
LikeLike
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).
LikeLike
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!
LikeLike