Loading
0xD0Lesson 14 of 17

Safe automation

Support -WhatIf in your own functions, use the output streams, catch mistakes with strict mode, and keep secrets safe.

28 min 7-question quiz 2 code exercises
By the end of this lesson you can
  • Make your functions support -WhatIf and -Confirm with SupportsShouldProcess
  • Use the verbose, warning and information streams, and redirect them
  • Catch mistakes early with Set-StrictMode, PSScriptAnalyzer and Pester, and handle credentials safely

Automation multiplies mistakes as easily as it multiplies work. PowerShell has unusually good guard rails - use them.

-WhatIf for your own functions. Add SupportsShouldProcess to [CmdletBinding()] and wrap every change in if ($PSCmdlet.ShouldProcess(target, action)) { ... }. Your function instantly gains -WhatIf and -Confirm, and it passes them on to the cmdlets it calls.

should-process.ps1
1function Remove-OldFeedLog {
2  [CmdletBinding(SupportsShouldProcess)]
3  param([Parameter(Mandatory)][string[]]$Name)
4  foreach ($log in $Name) {
5    if ($PSCmdlet.ShouldProcess($log, 'Delete feeding log')) {
6      "deleted $log"
7    }
8  }
9}
10Remove-OldFeedLog -Name 'monday.csv', 'tuesday.csv' -WhatIf
11Remove-OldFeedLog -Name 'monday.csv'
Output
What if: Performing the operation "Delete feeding log" on target "monday.csv".
What if: Performing the operation "Delete feeding log" on target "tuesday.csv".
deleted monday.csv

Six output streams

Results aren’t the only thing a command can produce. PowerShell has numbered streams, each with its own cmdlet:

#StreamWrite withShown by default?
1Success (output)Write-Output / bare valuesyes
2ErrorWrite-Erroryes
3WarningWrite-Warningyes
4VerboseWrite-Verboseonly with -Verbose
5DebugWrite-Debugonly with -Debug
6InformationWrite-Information (and Write-Host)Write-Host: yes

Sprinkle Write-Verbose through advanced functions: silent normally, a detailed narrative with -Verbose. Redirect streams like this: 3> warnings.txt, 2>&1 (errors into output), *> all.txt (everything).

streams.ps1
1function Invoke-Feeding {
2  [CmdletBinding()]
3  param([string]$Dragon)
4  Write-Verbose "Fetching food for $Dragon"
5  "$Dragon fed"
6}
7Invoke-Feeding -Dragon Ember
8Invoke-Feeding -Dragon Glim -Verbose 4>&1 | ForEach-Object { "[$_]" }
Output
Ember fed
[Fetching food for Glim]
[Glim fed]

Catching mistakes early

  • Set-StrictMode -Version Latest turns sloppy code into errors: using a variable that was never assigned, reading a property that doesn’t exist, calling functions with method syntax. Put it at the top of scripts.
  • PSScriptAnalyzer (Install-Module PSScriptAnalyzer, then Invoke-ScriptAnalyzer .\script.ps1) is the linter: unapproved verbs, aliases in scripts, unused variables, plain-text passwords and more. VS Code runs it as you type.
  • Pester is the test framework. Tests read almost like English:
1Describe 'Get-FeedingAmount' {
2  It 'doubles the amount for hungry dragons' {
3    Get-FeedingAmount -Wingspan 10 -Hungry | Should -Be 60
4  }
5}
strict-mode.ps1
1$dragon = 'Ember'
2"Without strict mode: [$dragn]"
3Set-StrictMode -Version Latest
4try {
5  "With strict mode: [$dragn]"
6} catch {
7  'Strict mode caught the typo: $dragn was never set'
8}
Output
Without strict mode: []
Strict mode caught the typo: $dragn was never set

Key takeaways

  • [CmdletBinding(SupportsShouldProcess)] plus $PSCmdlet.ShouldProcess() gives your functions -WhatIf and -Confirm.

  • Output, error, warning, verbose, debug and information are separate streams; redirect them with n>, 2>&1 and *>.

  • Set-StrictMode -Version Latest, PSScriptAnalyzer and Pester catch mistakes before they bite.

  • Keep secrets out of scripts: Get-Credential and SecretManagement.

Lesson quiz

7 questions · pass with 5 correct · up to 50 XP

Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.

Practice: write PowerShell scripts

Write a script in the editor and run it for real against sample input, which is piped into your script as $input. Scripts run on PowerShell 6.2 through Try It Online (tio.run), a free public service, so these exercises avoid PowerShell 7-only syntax; your script and test input are sent there.

Exercise 1

A cleanup that supports -WhatIf

+25 XP

Write Remove-FeedLog with [CmdletBinding(SupportsShouldProcess)] and a mandatory -Name parameter (a file name). It deletes that file from the current folder and outputs deleted <name>, but only when $PSCmdlet.ShouldProcess($Name, 'Delete feeding log') says so.

The starter creates a log file for each input line, rehearses deleting them all with -WhatIf, really deletes only the .old ones, and lists what’s left.

  • Three logs
script.ps1
Loading editor…

Lessons teach PowerShell 7; your script runs on PowerShell 6.2 via Try It Online (tio.run), a free public service, so stick to syntax that works there. Test input is piped into your script as $input. Your script and test input are sent to that service.

Exercise 2

Verbose feeding

+25 XP

Write an advanced function Invoke-Feeding that takes -Dragon and -Kilograms and outputs Ember fed 20 kg. Before that, it writes a verbose message: checking Ember's diet. If the kilograms are over 50 it writes a warning: Ember is getting a lot of food.

The starter calls it once normally and once with -Verbose, merging the verbose (4) and warning (3) streams into the output so you can see them.

  • Two dragons
script.ps1
Loading editor…

Lessons teach PowerShell 7; your script runs on PowerShell 6.2 via Try It Online (tio.run), a free public service, so stick to syntax that works there. Test input is piped into your script as $input. Your script and test input are sent to that service.

Questions about this lesson

Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.

Loading posts…

Did you like the lesson? 😆👍
Consider a donation to support our work: