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

Secrets of a PowerShell "Guru"

Secrets of a PowerShell "Guru"

Slide deck used for the 40 minute session presented at the E2EVC event in Madrid on May 4th 2024

Guy Leech

May 07, 2024

More Decks by Guy Leech

Other Decks in Technology


  1. WHOAMI  Wrote first code in 1980 on a Commodore

    PET  Computer Science degree (FWLIW)  6 years as a Unix device driver then app developer in C then C++  Started with Citrix (WinFrame) in 1995  Invented & wrote what is now Ivanti Application Control (was AppSense Application Manager)  150+ “useful” scripts on GitHub  Mostly write PowerShell, and other languages, for software vendors  Available for hire (hourly or daily) – code reviews, workshops, training, …
  2. START AS YOU MEAN TO GO ON  Don’t write

    dirty, lazy code hoping you will come back to it someday – you won’t!  Error handling from the get-go  Don’t hard code anything  Make it a parameter with a default value  Or define as a variable near the top of the script  Set-StrictMode –Version Latest (when developing/testing, not in script itself)
  3. CODE DEFENSIVELY  What could go wrong with this line/what

    happens if …  Check return codes/values  $?  -PassThru  Try/catch  (Script) Users do the stupidest things – code for it, don’t assume sanity  How could this be misused by a bad actor?  Will this work in another language?  Nobody would be stupid enough to … yes, they would  Protect credentials, secrets, etc  SecureString & PSCredendtial types  Azure Key Vault  Is this date/time local or UTC ?  Parameter validation – ValidateRange, ValidateSet, ParameterSetName, check

    knows or remembers everything  If they say they do they are either deluded or an idiot or both  Surely I can’t be the first person to have/want to write something like this?  If you use someone else’s code, give credit in your code & socials  And check it isn’t accidentally/deliberately malicious (test, test, test (not in prod))  Don’t get disheartened if it doesn’t work first time or make silly mistakes  Law of diminishing returns – know when to quit/seek help  Throwing time at a problem is no guarantee of success – take a break
  5. USE IT OR LOSE IT  Need to keep momentum

    going, not once every few months  Personal projects – I find them relaxing & fulfilling (I’m old & sad)  But don’t save 10 minutes by spending 10 days on it – balance!  Troubleshoot & administer via PowerShell not GUI, e.g. event logs  Live in PowerShell
  6. TEST  “If it isn’t tested, it’s broken”  Boundary

    conditions/edge cases  “What would an idiot do”  Pester  Breakpoints & change variable contents  Clean machine, new user, clean profile  Elevated or not?
  7. LIVE IN POWERSHELL, BANISH LEGACY CMD.EXE  Troubleshooting, automating, etc

    on the PS command line rocks!  History (Get-History or alias h) makes rinse & repeat easy  Ctrl r to search history (requires persistent user profile)  F2 toggles in line/list mode in pwsh 7.x  If running an exe, see if there is a native PS way (think objects!)  ipconfig.exe -> Get-NetIPConfiguration (alias gip)  icacls.exe -> Get-ACL & Set-ACL  Eat your own dog food aka run your own scripts & fix/improve  If it runs in cmd but not PS, work out why rather than admit defeat  Special characters  Quotes  Ctrl z/y, ctrl home/end, ctrl backspace/delete (Get-PSReadLineKeyHandler)
  8. READ THE ERROR MESSAGE(S)  And if it’s a fatal

    error, get the hell out of Dodge (abort! abort!)  But do you need to expose the actual error?  Can you script around it?  Can you output a link for more information/fix/workaround ?  Write-Warning instead ?  Don’t try/catch an exception & just output “there was an error”  $ErrorActionPreference = ‘SilentlyContinue’ – NO!!!  -ErrorAction SilentyContinue –ErrorVariable thisSpecificError  Try/catch with comment if ignoring exception (check it’s expected exception)
  9. SHARE AND SHARE ALIKE  Don’t try and obfuscate, e.g.

    compile  Unless protecting IP & methods are not always 100% secure  Don’t be embarrassed  Likelihood of something similar is usually high – why reinvent the wheel?  Ask the community for feedback  Accept suggestions, improvements & criticism graciously

    identifiers – no $i or $pw  Tab completion so length/brevity doesn’t matter & decreases tpyo [sic] risk  Set-StrictMode –Version Latest (when developing/testing, not in script itself)  Comments but allow code to be self-documenting as much as possible  PowerShell Approved Verbs – Verb-Noun for functions  Spaces are not evil – embrace the space  No cmdlet/function aliases  No parameter abbreviations  No positional parameters & use non-abbreviated named ones (tab complete)  Use parameters, with defaults, not variables that need editing in script
  11. USE OUTPUT STREAMS PROPERLY  Don’t use Write-Host for errors

     Don’t use Write-Host unless you really, really have to  Output helpful information with Write-Verbose so can be silenced without changing code  But use breakpoints in ISE or VS Code for debugging  Be careful with Write-Output if your script outputs objects – pipeline pollution  Write-Debug can be useful but watch for it prompting to continue  Use Write-Progress cautiously as can slow execution massively  Write-Information ??  Redirection of individual streams useful to separate them out (N>file)

    versus ISE  Notepad? NO!  Unless it’s a quick change or all you have got access to  Use what you know will be available (built in tools)
  13. PERFORMANCE TIPS  += on arrays can be slow because

    it copies the existing array to new  Hashtables (aka dictionaries) are great for caching  Keep loops lean & mean – evaluate as much outside as possible  Outputting objects in a loop & assigning to variable can be quicker  Beware pipeline pollution  Beware Where-Object on large arrays  Hashtable instead  BinarySearch method of Generic collections if they are sorted  Consider using runspaces for parallelisation  Jobs can be slow  ForEach-Object –Parallel in pwsh 7.x
  14. REFERENCES  Approved verbs  Guy’s github  Guy’s Pastebin

     Guy’s YouTube Channel  Guy’s Slide Decks  ScriptRunner – easy yet robust way for non-PS people to run your scripts  Get-Help & Get-Command & Get-Member & ctrl space/tab complete
  15. EXIT 0  Which reminds me, think about exit codes

    lest someone embeds your script  Throwing exceptions may not be caught by calling code