Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Learn How to PowerShell Like a Pro

Guy Leech
September 23, 2022

Learn How to PowerShell Like a Pro

See some tips from a professional PowerShell coder on how to write code which is robust, reusable, readable and right in order to make your life, and that of your co-workers/customers, easier.

Guy Leech

September 23, 2022

More Decks by Guy Leech

Other Decks in Technology


  1. whoami /user • Wrote my first code (on Commodore PET)

    in 1980 (in BASIC) • Unix developer in C/C++ for 6 years after graduation from University of Manchester (Comp Sci) • Started with Windows (NT 3.51) in 1995 via Citrix (installed via 35 floppies!) • Invented & wrote what is now Ivanti Application Control security product (was AppSense) • Freelance consultant writing PowerShell for software vendors like ControlUp, Flexxible IT, PolicyPak • Microsoft MVP, Citrix CTP, VMware vExpert, Parallels VIPP • Master of Dad jokes @guyrleech Slide 1 of 0xdead
  2. Why Write Robust Code? • Less comeback • Fewer problems

    to rectify afterwards • Higher successful outcomes • Why not? Do it as you code, not "later" so becomes habit • Reputation • "Write it once, write it right" @guyrleech
  3. Questions about Error Handling • Does it benefit the user

    if the error is reported? • Is there anything that can be done to avoid/predict the error? • Is there anything that can be done to fix the error? • Is it a fatal error or can we continue (change to warning)? • Does the error message make sense to mere mortals? • Change the error text to display remedial action, KB references, etc • Can the user actually deal with raw errors? @guyrleech
  4. Errors • Check for errors even if not obvious that

    has errored • Be Consistent • Expected errors (e.g. create folder when already exists) • If you explicitly ignore/hide an error have a comment saying why • Beware modules/cmdlets that output error to stdout • Or don't output errors at all or return status (and use Write-Host) • Zero can be error ($false) or success (ERROR_SUCCESS in Windows APIs) @guyrleech
  5. Checking for Errors • Validate return values • Abort, abort,

    abort! • $? • $error • Array • $error.Clear() • -ErrorVariable (works with –ErrorAction SilentlyContinue) • -PassThru • Extra checks, e.g. if folder creation, check folder created @guyrleech
  6. Exceptions • Designed to simplify error checking • Compromise –

    1x try catch around whole code vs try catch around everything • Can be ignored but is that wise? • Use $_ to examine exception in catch block • Catch specific exceptions if you are going to deal with them differently • catch [System.Management.Automation.DriveNotFoundException] • $_.Exception.gettype().FullName • Try catch finally – finally useful for tidy up like removing temp files • Beware error message containing "At line:1 char:1" @guyrleech
  7. Variables: Strong Typing & Initialisation • Declaring type helps catch

    static errors & helps intellisense • Script variables and parameters • Get type name from a variable via GetType().FullName • Declare and initialise to known value, typically $null or -1 • De-initialisation • Call Dispose(), Close() etc as relevant (Get-Member) • Set to $null when finished or even remove variable @guyrleech
  8. Additionally #1 • Comments (and update/delete them) • Meaningful variable

    names $i • $ErrorActionPreference = 'SilentlyContinue' Never! • But do use it on individual cmdlets as necessary/appropriate • $null and zero are different – which do you need to check for? -not • Check property exists before referencing if may be missing • If($null -ne $guysobject.PSObject.Properties[ 'SomeProperty' ] ) { • Invoke-SomeFunction –InputObject $guysobject.SomeProperty } • Use named parameters with full name, not positional or abbreviated • Sanity checks parameters as much as possible & give meaningful errors • No aliases in scripts, only use them interactively (or for tweets) @guyrleech
  9. Additionally #2 • Check size of array before indexing in

    to it • [-1] for last item • Check not $null before using Count property • Watch for array flattening where single item not returned as array • Wrap in @() • Opposite – get an array when expecting single item • Select –First/-Last • -is [array] • Use –as instead of [type] cast • TryParse & TryParseExact methods • [string]::IsNullOrEmpty() • Use extra parentheses if makes it easier to read/understand • If you are copying & pasting the same chunk of code, you should use functions @guyrleech
  10. Testing • Different PowerShell versions (#requires –version) • Different environments

    • Different operating systems • Admin vs non-admin (#requires -runasadministrator) • Edge cases (what if the user has (stupidly) done …) • Different users • "What If" code walk throughs @guyrleech
  11. Aids • Set-StrictMode • PSScriptAnalyzer • ISE Steroids • Pester

    • Code review • Other people's code @guyrleech
  12. References • Guy’s In Person PowerShell Workshops • https://powershellexplained.com/2017-04-10-Powershell-exceptions-everything- you-ever-wanted-to-know

    • https://docs.microsoft.com/en- us/powershell/module/microsoft.powershell.core/about/about_functions_advance d_parameters?view=powershell-5.1 • https://github.com/PowerShell/PSScriptAnalyzer • https://powershell.one/isesteroids/quickstart/overview • https://github.com/guyrleech @guyrleech