Slide 1

Slide 1 text

SECRETS OF A POWERSHELL “GURU” @guyrleech @E2EVC Madrid 2024 (0x7e8)

Slide 2

Slide 2 text

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, …

Slide 3

Slide 3 text

*WARNING* - VERY BORING SLIDES!

Slide 4

Slide 4 text

*WARNING* - VERY FEW DEMOS!

Slide 5

Slide 5 text

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)

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

DO NOT BE AFRAID/TOO PROUD TO SEEK HELP  Nobody 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

Slide 8

Slide 8 text

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

Slide 9

Slide 9 text

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?

Slide 10

Slide 10 text

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)

Slide 11

Slide 11 text

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)

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

WRITE BEAUTIFUL CODE – FUTURE YOU THANKS YOU  Meaningful 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

Slide 14

Slide 14 text

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)

Slide 15

Slide 15 text

USE THE TOOLS YOU FEEL COMFORTABLE WITH  VS Code 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)

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

MISCELLANEOUS  40+ years of development definitely helps

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

EXIT 0  Which reminds me, think about exit codes lest someone embeds your script  Throwing exceptions may not be caught by calling code