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