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.
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
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
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
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
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
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
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
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
• 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