How to make your PowerShell scripts look better

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 certain 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’s basically putting 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"

Same thing as above, could require scrolling and 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 do this by just typing 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 options mentioned above, 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 πŸ™‚

One thought on “How to make your PowerShell scripts look better

  1. Pingback: Power of Windows PowerShell - AnyWare IT Solutions Pte Ltd

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.