Tips and notes for better PowerShell scripting.

This article contains my notes from completing Learn PowerShell in a Month of Lunches.

In the spirit of avoiding the online recipe pattern, the context comes after the notes.

Notes

Must remember

  • In PowerShell everything is an object
    • To get the properties/methods of an object : ... | Get-Member
    • To see what is accepted as pipeline input : Get-Help ... -full
    • To strongly type / cast a variable : [int]$number = Read-Host "Enter a number"
  • Always try to pipe commands first
    • When binding is not possible, then use (...). As an example:
      • This is not supported: Get-Content .\computers.txt | Get-WmiObject -class win32_bios
      • The alternative : Get-WmiObject -class Win32_BIOS -ComputerName (Get-Content .\computers.txt)
  • Vocabulary
    • “Host” = screen (as in Write-Host)

Practical

  • Syntax
    • ${My Variable} for variable with spaces
    • Use $(...) to run a command in a string: $firstname = "The first name is $($services[0].name)", here the command is $services[0].name
  • Unboxing a property via Select-Object
    • ...| Select-Object -expand name
    • Similar to (...).name which also returns a string
    • As opposed to ...| Select-Object -property name which returns an object with the unique property name
  • Aggregating in the pipeline
    • ... | Measure-Object -property A -sum
  • File parsing:
    • To open a file: Get-Content
    • Use Import-CSV or Import-CliXML instead to get automatic parsing from file structure
    • For JSON it’s still Get-Content ... | ConvertFrom-Json
  • Invocation operator: & (doc)
    • or --% (same but with literal parsing of arguments)
    • The syntax is weird in the sense that arguments are passed as PowerShell arguments and not string: & sa.exe -p1 "AH" -p2 "HA"
  • Wildcard characters: * for 0 or more char, ? for any single one
    • -LiteralPath instead of -Path to prevent wildcard interpretations
  • Background jobs
    • Enable-PSRemoting to Start-Job even local
    • Don’t ever make assumptions about file paths from within a background job: Use absolute paths to make sure you can refer to whatever files your job command may require

  • In a script there’s only one pipeline, so your scripts should strive to output only one kind of object

Cute

  • Show-Markdown will show a string or file in the console rendering the Markdown syntax
  • ... > my.txt is equivalent to ... | Out-File my.txt
  • The percent sign (%) is an alias to ForEach-Object
  • Variables
    • PowerShell home : $pshome
    • PowerShell version “ $PSVersionTable
  • Don’t use Write-Host for fuzzy status
    • Use Write-Verbose, Write-Debug, Write-Warning, Write-Error
    • Leverage their settings $VerbosePreference="Continue" and call parameters .\myScript.ps1 -verbose

Context

As I’ve recently been using PowerShell more and more, I’ve decided to take the time to learn it properly.

I had bought Learn PowerShell in a Month of Lunches previously but never had taken the time to go through it. So I did. And I don’t regret it. Both the format and the content are fantastic, I highly recommend it to anyone looking to get a strong foundation in PowerShell.

Cover of Learn Windows Powershell in a Month of Lunches

Learn Windows Powershell in a Month of Lunches

Now why would one want a good foundation in PowerShell? Because everyone needs to be comfortable in at least one shell. It is fairly simple and yields huge benefits in automating all sort of processes via the command line. PowerShell is of course the perfect candidate when you’re deep in Microsoft territory (so easy to leverage in Azure). And since it’s cross platform now!

Sample of PowerShell code - look at me flexing my mad

Sample of PowerShell code, the rest here

I’m starting Learn PowerShell Scripting in a Month of Lunches now, the follow-up to Learn PowerShell… focusing on scripting. I’ll surely add to the list of tips below when I’m done.