using consoles from (multiple) vendors • Bulk/repeated operations • Scheduled tasks to report/fix • Easy to import/export to csv/xml/json and send emails • Can use interactively or via scripts • Tab completion of commands, arguments, parameters • Intuitive/consistent – it’s a shell *AND* a scripting language • Huge number of scripts and learning resources out there • But check untrusted scripts before running them as admin on production systems! • Cross Platform • Fame, fortune, ….
you found them • Set-ExecutionPolicy –Scope Process • Old version • #Requires -version • $PSVersionTable • Avoid 2.0 – upgrade/install Windows Management Framework • Spaces in script names • Relative paths • Not running elevated or under an account with sufficient permissions • Parameters – missing mandatory ones • Not reading error text • Script readability • Putting everything on a single line • But assigning everything first can slow scripts down & increase memory usage (pipe through ForEach-Object)
facing infrastructure servers like Delivery Controllers, PVS (unless need to manipulate local store) • -AdminAddress (on every call – consider splatting) • -MaxRecordCount • Cloud – create credential profile via downloaded secrets csv file
oriented SDK around 7.8 • Prior to that was MCLI.exe and text results ☹ • Do not use PvsPsSnapIn snapin as only has 11 cmdlets • Import-Module "$env:ProgramFiles\Citrix\Provisioning Services Console\Citrix.PVS.SnapIn.dll" • 178 cmdlets • Do not run on PVS server unless need to manipulate local store
state/power state per delivery group/tag • Overdue reboot • High PVS retries • High user load • Low disk space • Remediation • Etc, etc • Check spoolers and shared printers • Consume “Director” data (via OData/REST) • Ghost sessions • … and whatever else you do repetitively
properties and methods are available by piping to Get-Member (gm) • Assign result to variable or pipe through “Select –First 1” • Filter on some properties • Where-Object { $_.something –eq ‘interesting’ –and $_.somethingelse –ne 42 } • Check if cmdlet itself can filter as filtering as far left as possible is best for speed & efficiency • Pipe to Export-CSV • Pipe to Out-GridView • Pipe to other cmdlets • Get-ChildItem \blah | Where LastWriteTime -lt (Get-Date).AddDays(-120) | Remove-Item • Email via Send-MailMessage • SMTP but can use Invoke-Command to proxy mail off another machine if relaying restricted
like system32 in case you create/delete files • cd $env:userprofile • Can put in profile $env:userprofile\Documents\WindowsPowerShell\profile.ps1 • [console]::Title = ‘Server XXX’ • [console]::ForegroundColor = ‘Cyan’ • Use different colours for different users, systems, etc. • Sit in PowerShell.exe all day, not cmd.exe, so you get used to it • Set-StrictMode –version Latest • $PSVersionTable • $pid • Get-Alias • But do not use aliases in scripts as makes difficult to understand
and leave them as you found them • Get-ExecutionPolicy / Set-ExecutionPolicy • Double click explorer action should be left as edit for safety • Explorer right click “Run with PowerShell” should be avoided • Invoked window will close when finished so you can’t see errors/results • Cannot pass non-mandatory parameters • Like Unix/Linux shells, script must be in $env:Path or specify full or relative path (.\) • Must put single or double quotes around any script/argument which has spaces in the name and prefix with & • Without out & it will just echo the script name back to you – “hello world” • Double quotes causes PowerShell to evaluate $ variables, etc.
for missing mandatory arguments • Use tab completion after typing – after the script name to cycle through available parameters • And when typed first few characters of option, e.g. –verb, although can leave as shortened form if not ambiguous • Be aware of any version restrictions e.g. #Requires lines • Run with –WhatIf if the script can be destructive • Although developer can choose to ignore
PowerShell script • [CmdletBinding] also means can use common options like –Verbose, -WhatIf, -Confirm, etc. • But script writer still has to wire them up • Script can have named parameter sets to try & stop people using wrong combinations of options • Parameter validation can be coded so only certain things allowed, e.g. –ErrorAction • Parameters can be dynamically presented, e.g. Get-Process –Name • Parameters may take patterns or regular expressions (regex) • Passing some options in via cmd or Scheduled tasks can cause problems • $true/$false • Arrays
to update help • Run Get-Help <scriptname> • Level of info will depend if author has put in correctly formatted help system comments • Run the script with -? • Look at the script! • Web search • Ask the audience
• Load into ISE and set breakpoints via F9 • Can examine variables when breakpoint hit • Add Write-Output/Write-Verbose/Write-Debug lines where you need them • Keep an unadulterated copy of the script in case you break it! • Be careful, particularly if running as an admin on a production system
• Read and digest the error message! • Does it need to run elevated or on a specific machine where cmdlets, etc. are available? • They may be terminating or script may carry on – depends on how script written & type of error • Look at the line number referenced, put a breakpoint in and examine variables • -ErrorAction / -EA but do not turn off error reporting • Try/Catch blocks catch thrown exceptions & may not output any messages (could be expected error) • Capture to file/screenshot • Web search
that runs a PowerShell script • Create task folder to keep all custom tasks in one place • Write a log file • Start-Transcript / Stop-Transcript • Can get problems with embedded strings, $true/$false and arrays • Execution Policies • Powershell.exe –executionpolicy bypass • Test command line via cmd.exe • Does it need a dedicated service account? Practise LUA!
csv format file so can sort, filter, etc. in Excel • Run a cmdlet and pipe through Export-CSV and voila you have captured that information to file • Get-BrokerMachine | Export-CSV –Path xenapp7.machines.csv -NoTypeInformation • Specify –NoTypeInformation and –NoClobber • Can also show on screen in a grid view by piping to Out-GridView instead of Export-CSV • E.g. if Excel not available • Import-CSV existing.info.csv | Out-GridView • Can import from a CSV directly into a variable and then process it – each column will be a . value • $data = Import-CSV existing.info.csv
other people’s scripts • Don’t be frightened but do be careful • Don’t logon, let alone run scripts as an admin, unless you really have to • Use [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='High')] and $PSCmdLet.ShouldProcess() • Don’t run on live systems where possible • Single step/set breakpoints before destructive actions • Sanity check parameters passed – don’t assume everyone will understand your parameters • If at first you don’t succeed, try, try again • Bite size chunks – plan version features/contents • Don’t hardcode – use parameters or variables • ISE is your friend, make use of breakpoints (some say Visual Studio Code is better) • Don’t copy and paste chunks of code – put it in a reusable Function • Use Write-Verbose or Write-Debug for status/debug messages, not Write-Host as can't be redirected • Neglect error checking and handling at your peril!
script from scratch, know how to figure out roughly what it does & is safe to run • Someone has probably written some of what you want already – search, find and plagiarise/improve (even I do but credit the originator!) • Don’t brag about not being able to write scripts – it’s not big or clever and limits/slows you • Don't worry about style, performance, etc to start with – the main thing is to solve the problem • Scripting can be an art form and can be therapeutic, yes really • What tools still need writing to help you become more efficient? • Writing stuff is, relatively speaking, easy but having the ideas is the difficult bit (and what to call it!) • If you find/write something useful, share it