When I started writing my first PowerShell scripts… They didn’t look that good, it was PowerShell 2.0, of course, and I was just a beginner π I’m getting better at it, and the newer versions of PowerShell (And Visual Studio Code) have a few nice formatting tricks. This blog post will show you a few ways to make your scripts look better and, more importantly… A lot more readable!
Comments
Something that I sometimes forget to do in smaller scripts, but it’s a good thing to do for everyone reading your script by letting them know what a specific part of the script does. You can use a # before a line to write a comment on that line or use <##> to write a comment containing multiple lines (Write in between the #’s). Simple short example:
#Retrieve all .txt files older than 30 days Get-Childitem -Path c:\temp -Filter *.txt | Where-Object LastWriteTime -LT (Get-Date).AddDays(-30)
or this version with more details:
<# The command below searches for txt files in c:\temp which have a Last Write longer than 30 days ago #>
Don’t use aliases or shortened commands
You can shorten your commands or use aliases so that you have to type less in a PowerShell command line. This is great because you save typing a lot of letters… It’s not very readable when using it in scripts… For example:
dir c:\temp | where Name -match 'x' | % {Write-Host $_.Fullname}
I used ‘dir’ here instead of Get-Childitem, ‘where’ instead of Where-Object, and ‘%’ instead of Foreach-Object. To make it more readable, it would look something like this:
Get-ChildItem c:\temp | Where-Object Name -match 'x' | ForEach-Object {Write-Host $_.Fullname}
How to shorten long command-lines
It’s always nice to have a cmdlet with many parameters so that you can create the ultimate one-liner π But if that one-line doesn’t fit your screen anymore… Then it’s not very nice to read when scrolling through your script. PowerShell introduced Splatting in version 3.0, it puts your parameters in a hash-table with value pairs.
For example, you could have this command line for sending a log file to a certain email-address
Send-MailMessage -From harm@powershellisfun.com -To admin@powershellisfun.com -Subject 'Errors found on server' -Body 'See attached logfile for more information' -Attachments C:\temp\log.txt -Priority High -SmtpServer mail.domain.com
You had to scroll all the way right to read it. Not very readable. When using Splatting, it looks like this:
$options = @{ From = 'harm@powershellisfun.com' To = 'admin@powershellisfun.com' Subject = 'Errors found on server' Body = 'See attached logfile for more information' Attachments = 'C:\temp\log.txt' Priority = 'High' SmtpServer = 'mail.domain.com' } Send-MailMessage @options
Looks a lot better and way more readable π
How to make arrays more readable
You can create an array variable containing multiple values in one line just by doing this:
$capitalcities="Amsterdam", "Berlin", "Brussels", "Dublin", "London", "Madrid", "Monaco", "Oslo", "Paris", "Prague", "Rome"
The same thing as above it could require scrolling and is not very readable. Looks more readable when formatting it like this:
$capitalcities = @( "Amsterdam", "Berlin", "Brussels", "Dublin", "London", "Madrid", "Monaco", "Oslo", "Paris", "Prague", "Rome" )
Specifying executables
If you have to call an executable from within your script, you can type it without the .exe or .com. While this does work, it doesn’t tell the one reading your script if you used a function or an alias. So, change: (Snippet of an old script that outputs Scheduled Tasks to a file)
schtasks /Query /FO CSV /s $server.Name /v > $env:TEMP\schedulestask.txt
to this:
schtasks.exe /Query /FO CSV /s $server.Name /v > $env:TEMP\schedulestask.txt
or even better by specifying the whole path:
C:\Windows\System32\schtasks.exe /Query /FO CSV /s $server.Name /v > $env:TEMP\schedulestask.txt
Using Visual Studio code for formatting
And now is the best option for making PowerShell scripts more readable.. Visual Studio Code π You can create a script in VSCode with all the abovementioned options, but it could still be not that nice to read. For example: (Snippet from my SSID_Passwords script)
if ($null -ne $wlanprofiles) { foreach ($wlanprofile in $wlanprofiles | Sort-Object) { try { $profile_information=netsh wlan show profile name="$($wlanprofile.ToString().Split(':')[1].SubString(1))" key=clear write-host Retrieving password for SSID $wlanprofile.ToString().Split(':')[1].SubString(1) -ForegroundColor Green $password=[PSCustomObject]@{ 'SSID'=$wlanprofile.ToString().Split(':')[1].SubString(1) 'Authentication Type'=($profile_information | select-string 'Authentication' | Select-Object -First 1).Tostring().Split(':')[1].Substring(1) Password=($profile_information | select-string 'Key Content').Tostring().Split(':')[1].Substring(1) } $passwords += $password } catch { #If retrieving the password fails, add the reason why to $passwords in the password field $authenticationtype=($profile_information | select-string 'Authentication' | Select-Object -First 1).Tostring().Split(':')[1].Substring(1) write-host "Could not retrieve password for SSID $($wlanprofile.ToString().Split(':')[1].SubString(1)), check $($output)" -ForegroundColor Red $password=[PSCustomObject]@{ 'SSID'=$wlanprofile.ToString().Split(':')[1].SubString(1) 'Authentication Type'=($profile_information | select-string 'Authentication' | Select-Object -First 1).Tostring().Split(':')[1].Substring(1) Password="Could not retrieve password for the SSID because it's an $($authenticationtype) network" } $passwords += $password } } }
In VSCode, you can Right-Click and choose Format Document:

And then your code looks like this π (Format does look different because of WordPress formatting, but copy/paste it into your VSCode or ISE to see the difference)
if ($null -ne $wlanprofiles) { foreach ($wlanprofile in $wlanprofiles | Sort-Object) { try { $profile_information = netsh wlan show profile name="$($wlanprofile.ToString().Split(':')[1].SubString(1))" key=clear write-host Retrieving password for SSID $wlanprofile.ToString().Split(':')[1].SubString(1) -ForegroundColor Green $password = [PSCustomObject]@{ 'SSID' = $wlanprofile.ToString().Split(':')[1].SubString(1) 'Authentication Type' = ($profile_information | select-string 'Authentication' | Select-Object -First 1).Tostring().Split(':')[1].Substring(1) Password = ($profile_information | select-string 'Key Content').Tostring().Split(':')[1].Substring(1) } $passwords += $password } catch { #If retrieving the password fails, add the reason why to $passwords in the password field $authenticationtype = ($profile_information | select-string 'Authentication' | Select-Object -First 1).Tostring().Split(':')[1].Substring(1) write-host "Could not retrieve password for SSID $($wlanprofile.ToString().Split(':')[1].SubString(1)), check $($output)" -ForegroundColor Red $password = [PSCustomObject]@{ 'SSID' = $wlanprofile.ToString().Split(':')[1].SubString(1) 'Authentication Type' = ($profile_information | select-string 'Authentication' | Select-Object -First 1).Tostring().Split(':')[1].Substring(1) Password = "Could not retrieve password for the SSID because it's an $($authenticationtype) network" } $passwords += $password } } }
These were just a few tips/tricks for making your PowerShell scripts look nice, enjoy π
Pingback: Power of Windows PowerShell - AnyWare IT Solutions Pte Ltd