Functions
Scope: defining functions, parameters, and pipeline input. All examples were run with PowerShell 7.5.
Basic functions
function Get-Greeting {
param([string]$Name = "stranger")
return "Hello, $Name!"
}
Get-Greeting -Name "Ada" # Hello, Ada!
Get-Greeting # Hello, stranger!
Verb-Nounnaming, same as cmdlets.param()declares parameters with optional types and defaults.- Call with spaces and dashes, not parens:
Get-Greeting -Name "Ada", neverGet-Greeting("Ada").
Output is return
In PowerShell, everything the function outputs is its return
value — there's no separate return channel:
function Get-Numbers {
Write-Host "working..." # screen only, NOT returned
1, 2, 3 # this IS returned
}
$result = Get-Numbers # $result = 1, 2, 3
This is the #1 surprise for newcomers: stray output (a command
you forgot to capture, a Write-Output) becomes part of the
return value. Write-Host is safe (screen only); bare values
and uncaptured commands are returned.
return "x" is just "output x and exit now" — convenient, but
output-before-it counts too.
Advanced functions: cmdlet behavior
function Get-Even {
[CmdletBinding()]
param(
[Parameter(Mandatory, ValueFromPipeline)]
[int]$Number
)
process {
if ($Number % 2 -eq 0) { $Number }
}
}
[CmdletBinding()] gives your function cmdlet superpowers:
-Verbose, -WhatIf, -Confirm, common parameters. The
begin/process/end blocks handle pipeline input —
process runs once per piped object:
1..6 | Get-Even # 2, 4, 6
Write advanced functions for anything shared; simple functions for quick helpers.
Parameter validation
function Set-Mode {
param(
[ValidateSet("on", "off")]
[string]$State,
[ValidateRange(1, 10)]
[int]$Level = 5
)
Write-Host "$State at level $Level"
}
[ValidateSet()] restricts to known values (with tab
completion!), [ValidateRange()] bounds numbers,
[ValidateNotNullOrEmpty()] rejects empties. Validation beats
manual if checks.
ShouldProcess: -WhatIf support
function Remove-OldLogs {
[CmdletBinding(SupportsShouldProcess)]
param([string]$Path)
if ($PSCmdlet.ShouldProcess($Path, "Delete old logs")) {
Remove-Item "$Path\*.log" -ErrorAction SilentlyContinue
}
}
With SupportsShouldProcess, -WhatIf shows what would
happen without doing it — the safe way to write destructive
functions.
Check
- [ ] You define
function Verb-Nounwithparam()and call with-Name valuesyntax - [ ] You can explain why stray output becomes return data
- [ ] You know what
[CmdletBinding()]buys you
Next: Objects and the Pipeline.