Press "Enter" to skip to content

My Top 10 PowerShell Tips & Tricks

Joshua Stenhouse 0

A few weeks ago I shared my top 10 PowerShell tips and tricks to becoming a PowerShell ninja on a webinar with IDERA, a highly regarded purveyor of SQL monitoring and auditing software. I covered everything from using comments, variables, to IF statements, logging, arrays, best practices, and lots of useful tips in-between. Basically everything I’ve learned to use and frequently do over the past 5 years of writing PowerShell.

If you’re interested in listening to me walk you through my top 10 then enter your information on the below link to access the recording:

https://www.idera.com/resourcecentral/webcasts/10-tips-powershell-ninja

While delivering the webinar I gave some example scripts to try yourself. I’m not going to share the most outrageous example on the webinar as that’s for another post. But for everything else you can save time by downloading them from the link below, or read through the rest of the post:

Top10PowerShellIderaWebinarExamplesv1.zip

I took some time to spruce them up and make sure they are working perfectly. I even copied from one of the examples myself last week! But that’s not all. I don’t want to be the person that brings you to a post and doesn’t give you the actual content. So, here are my top 10 PowerShell tips and tricks:

  1. General advice (9 tips in 1)
    – Get your hands dirty, you’ll only learn by trying
    – Keep it simple stupid, find a solution that works then boil it down
    – If you find a simpler method, go back & improve
    – Test each section of your script as you go along
    – Temporarily assign variables (read tip 3) to influence input & output
    – Use the right tool for the right job
    – I.E Visual Studio Code, PowerShell ISE, Notepad ++
    – Build your own library of scripts with versioning
    – Become your own best resource

  2. Frequent #comments are your best friend
    ######################
    # Create sections of script
    ######################
    # And explain individual actions within each section
    

    – Comments start with a hash, everything after ignored by the script
    – Use comments frequently, every 5-10 lines
    – 30-50% of a good script is comments
    – Explain complex elements, consider an index in large scripts
    – Make your scripts easier to read for everyone, including yourself

  3. Use unique $variables as your building blocks
    $Variable1 = 1
    $Variable2 = 2
    $Variable3 = $Variable1 + $Variable2
    "Result: $Variable3"
    

    – Variables are used to store & manipulate data
    – Use at the start of a script as building blocks
    – Remove repetitive hardcoded strings
    – Increase flexibility, easier to re-use & change
    – Store results, perform calculations etc
    – Don’t overwrite variables, it’s usually better to use new

  4. Use Start-Transcript and Stop-Transcript to enable logging in your scripts
    # Building log filename
    $Now = Get-Date
    $Log = "C:\Test\Log" + $Now.ToString(" yyyy-MM-dd_HH-mm-ss") + ".log"
    # Start logging
    Start-Transcript -Path $Log
    # Your script here
    "Hello World"
    # End logging
    Stop-Transcript
    

    – Transcript logging enables you to capture errors on headless scripts
    – Combine with returning variables and text in “comments” to indicate the progress of the script
    – Good for long & intricate scripts
    – Unnecessary with short ad-hoc scripts
    – Increase trust & visibility
    – Aid with compliance & auditing, which account ran the script on which machine and when

  5. Use Try and Catch to improve script resilience
    # Run the below to see an error not handled gracefully
    $Host = "Test"
    # Now try the same command inside a Try & Catch with the error shown in full
    Try
    {
    $TrySuccess = $True
    $Host = "Test"
    }
    Catch
    {
    "Don't try to overwrite the host variable dummy!"
    $TrySuccess = $False
    $_.Exception.ToString()
    $error[0] | Format-List -Force
    }
    # Showing result
    "TrySuccess:$TrySuccess"
    

    – Enables graceful error handling and captures errors
    – Use when working with external resources
    – Nest try commands to try again with sleep x for a delay
    – Big differentiation in quality

  6. Import-CSV and Export-CSV links everything to everything

    $CSVFileName = "C:\Test\ProcessList.csv"
    $ProcessList = Get-Process
    $ProcessList | Export-CSV $CSVFileName -NoTypeInformation
    $ProcessCSV = Import-CSV $CSVFileName 
    $ProcessCSV | Format-Table
    

    – Comma-separated value lists are good for the import & export of data at scale
    – Universal file format, most systems can export as CSV of raw data as a minimum
    – Use and combine data from multiple sources
    – Import list of objects to process from any application
    – Export results for use in other applications
    – Make your scripts user and machine friendly

  7. Use IF ($this -eq $that) {“Do this”} to make conditional decision making

    $Variable1 = 1
    IF ($Variable1 –eq 1)
    {
    "Yes"
    }
    ELSE
    {
    "No"
    }
    

    – Perform different actions based on variable
    – Can also use to bypass sections of a script
    – Nest multiple IF statements for even more flexibility, but
    – Don’t go to inception levels of nesting as it can be hard to troubleshoot
    – Can be used in reverse, I.E -ne, many options
    – Use comments to signify the end of IF statement in long scripts

  8. Repeat actions using ForEach ($This in $That) {“Do this”}
    $Servers = “Server1”,”Server2”,”Server3”,”Server4”
    ForEach ($Server in $Servers)
    {
    “Running script for Server: $Server”
    }
    

    – Repeat blocks of a script for multiple objects
    – Great for automating large manual tasks
    – Use sleep timers to wait in-between if needed
    – Combine with CSVs for even more power!
    – Learn this back to front

  9. Leverage PowerShell modules where available
    # Showing all modules available and a count
    $AllModules = Find-Module | Sort-Object Name
    "ShowingModules:"
    $AllModules | Format-Table
    "TotalModules:"
    $AllModules.count
    # Install, import, then show all commands in the SqlServer module
    Install-Module -Name SqlServer -Scope CurrentUser -Confirm:$false
    Import-Module SqlServer
    Get-Command -Module SqlServer | Format-Table
    

    – Use the PowerShell Gallery to install modules
    – Modules are pre-built cmdlets to extend the functionality
    – Use existing groundwork to save time, I.e the SqlServer module
    – 3189 available last time I counted
    – Not all are perfect or free

  10. If no module exists use Invoke-RestMethod to talk direct with REST APIs
    # This is an example using the Google maps API key, I beleive its still free for 25k requests per day but annoyingly you now have to enter billing info
    # To get your key go to https://developers.google.com/maps/documentation/geocoding/get-api-key and select places
    # I recommend restricting your API key usage to your IP address and I used my hometown of Todmorden UK as an example lookup
    $GoogleMapsAPIKey = "yourgooglemapsAPIkeyhere"
    $City = "Todmorden"
    # Building URI (a URL is a type of URI)
    $GoogleMapQueryURI = "https://maps.googleapis.com/maps/api/geocode/json?address=" + $City + "&key=" + $GoogleMapsAPIKey
    # Invoking the REST API call
    Try 
    {
    $GoogleAPICallSuccess = $TRUE
    $GoogleMapsResponse = Invoke-RestMethod -Method GET -Uri $GoogleMapQueryURI -ContentType "application/json"
    }
    Catch 
    {
    $GoogleAPICallSuccess = $FALSE
    $_.Exception.ToString()
    $Error[0] | Format-List -Force
    }
    # Extracting the data from the response
    $GoogleMapResults = $GoogleMapsResponse.results
    $Location = $GoogleMapResults.address_components.long_name | Select -Skip 1
    # Showing result
    "API Successfully called:$GoogleAPICallSuccess
    The town/city $City is in:"
    $Location
    

    – REST (Representational State Transfer) an approach
    – API (application programming interface) is a set of rules & mechanisms by which applications interact
    – JSON (JavaScript Object Notation) syntax for storing & exchanging data, most common data format, natively processed
    – Open up a world of possibilities, not limited to existing modules
    – Learn more about Invoke-RestMethod, increasing in use in the PowerShell community

  11. (Bonus tip) Create tables (an array) to store multiple variables
    # Creating table object
    $Table = @()
    # Showing you an example within a ForEach loop
    $Rows = "Row1","Row2","Row3"
    ForEach ($Row in $Rows)
    {
    # Adding Row
    $TableRow = New-Object PSObject
    $TableRow | Add-Member -MemberType NoteProperty -Name "Name" -Value "$Row"
    $TableRow | Add-Member -MemberType NoteProperty -Name "DataField" -Value "100"
    $Table += $TableRow
    }
    # Showing table after ForEach section
    $Table | Sort-Object Name | Format-Table
    # Adding the values together
    $TotalDataField = $Table | Select -ExpandProperty DataField | Measure -Sum | Select -ExpandProperty Sum
    $TotalDataField
    

    – Use for building tables of data
    – Collate data from multiple sources
    – Use cases include reporting, export to CSV etc
    – I.E ForEach X in X I need to store X results

And that’s it. All I need to do now is make sure I continue to adhere to my own tips and tricks! If you enjoyed this post follow me on twitter to stay up to date with my latest content and ramblings,

Leave a Reply

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

%d bloggers like this: