PowerShell Advanced functions
Adding [CmdletBinding()] above param() turns a plain function into an advanced function. The single line gets you every common parameter for free: -Verbose, -Debug, -ErrorAction, -WarningAction, -ErrorVariable, -OutVariable and more.
Documentation: Microsoft Learn
Overview
That is what makes Write-Verbose useful. Without [CmdletBinding()] there is no -Verbose switch to turn the messages on. With it, your verbose lines stay silent by default and appear on demand, which is how every built-in cmdlet behaves.
[CmdletBinding(SupportsShouldProcess)] goes further and gives you -WhatIf and -Confirm. Guard the state-changing line with if ($PSCmdlet.ShouldProcess($target)) and callers get a dry run for free. Any function that deletes, stops or overwrites something should have this.
The cost of [CmdletBinding()] is that PowerShell becomes strict about arguments: unknown parameters are now errors rather than being swept into $args. That strictness is the point.
Inspect this example’s structure
Read the command and its supplied arguments. This example requires real PowerShell or its module; this diagram does not execute it.
function Get-BigProcess {
[CmdletBinding()]
param(
[int] $MinimumMB = 200
)
Write-Verbose "Filtering processes above $MinimumMB MB"
Get-Process |
Where-Object { $_.WorkingSet64 -gt ($MinimumMB * 1MB) } |
Select-Object Name, Id, @{ Name = 'WS_MB'; Expression = { [math]::Round($_.WorkingSet64 / 1MB, 1) } } }
Get-BigProcess -MinimumMB 400 -Verbose- Stage 1function
-MinimumMB -Verbose
What happens
[CmdletBinding()] on line 2 is what makes -Verbose on the last line work. Run the call without -Verbose and the Write-Verbose line produces nothing.
The Select-Object uses a calculated property: a hashtable with Name and Expression keys, where the expression converts bytes to megabytes. That is how you add a column that does not exist on the original object.
Playbook rule
Use -WhatIf before destructive cmdlets.
Add -WhatIf to preview what a destructive cmdlet would do — nothing on your system changes until you run it again without the switch.
PS> Remove-Item C:\temp\old.log -WhatIf What if: Performing the operation "Remove File" on target "C:\temp\old.log".
Nothing was deleted. -WhatIf only describes the action it would take.
PS> Remove-Item C:\temp\old.log (no output — the file is gone)
Without -WhatIf there is no preview and no undo. This panel is a simulation — nothing on your machine was actually removed.
Worth remembering
- [CmdletBinding()] adds -Verbose, -ErrorAction and the other common parameters.
- Write-Verbose only does anything once -Verbose exists.
- SupportsShouldProcess adds -WhatIf and -Confirm.
- Unknown parameters become errors instead of landing in $args.
Primary documentation
Where-Object reference · Select-Object reference · Get-Process reference
Try it
Illustrative output · values vary by environment
Example reader
Inspect this page's example
Run supported commands against the practice data, or inspect the example without executing it.
Ready to inspect.
An advanced function using -Verbose and a calculated property.
Show reference output
Illustrative output · values vary by environment
VERBOSE: Filtering processes above 400 MB Name Id WS_MB ---- -- ----- chrome 9184 464.0 msedge 7133 521.4
Keep going
Next: PowerShell Pipeline bindingCheck your understanding
Your advanced function removes files. Does adding CmdletBinding alone implement a safe WhatIf path?
No. Declare SupportsShouldProcess and guard each change with $PSCmdlet.ShouldProcess. Confirm that the guarded branch contains the actual operation.