Functions, Parameters & Safe Tools
25 minStop retyping the same one-liners. Package your logic into reusable, well-behaved functions with typed parameters, mandatory inputs, object output, and built-in -WhatIf safety.
- ▸Define a function using the Verb-Noun naming convention and understand why approved verbs matter
- ▸Declare typed parameters with param() including default values and [Parameter(Mandatory)] constraints
- ▸Emit objects from a function instead of Write-Host so output is pipeline-friendly
- ▸Promote a function to an advanced function with [CmdletBinding()]
- ▸Add SupportsShouldProcess so callers get -WhatIf and -Confirm for free
Turning One-Liners Into Tools
A function is a named, reusable block of logic. Once defined, it behaves exactly like any built-in cmdlet — it accepts parameters, works in a pipeline, and returns objects.
Verb-Noun naming
PowerShell enforces a Verb-Noun convention (e.g. Get-DiskReport, Restart-StaleService). The verb should come from the approved list:
Get-Verb # shows all approved verbs
The basic skeleton
function Get-Greeting {
'Hello, world!'
}
Get-Greeting
Any expression not captured by a variable is automatically emitted to the pipeline — no return keyword required.
Adding parameters with param()
function Get-Greeting {
param(
[string]$Name = 'World'
)
"Hello, $Name!"
}
Get-Greeting -Name 'Alice'
- Type constraint
[string]coerces or rejects incompatible input. - Default value
= 'World'makes the parameter optional.
Mandatory parameters
function Get-Greeting {
param(
[Parameter(Mandatory)]
[string]$Name
)
"Hello, $Name!"
}
Omitting -Name now prompts the caller rather than silently using $null.
Returning objects, not text
Avoid Write-Host inside reusable functions — it writes to the screen only and breaks pipelines. Emit a [pscustomobject]:
function Get-DiskReport {
param([string]$ComputerName = $env:COMPUTERNAME)
$disk = Get-PSDrive C
[pscustomobject]@{
ComputerName = $ComputerName
UsedGB = [math]::Round(($disk.Used / 1GB), 2)
FreeGB = [math]::Round(($disk.Free / 1GB), 2)
}
}
Get-DiskReport | Export-Csv disks.csv -NoTypeInformation
Advanced functions and SupportsShouldProcess
Adding [CmdletBinding()] unlocks the common parameters (-Verbose, -ErrorAction). For any function that changes state, add SupportsShouldProcess and wrap the destructive call in $PSCmdlet.ShouldProcess(...). Callers then get -WhatIf and -Confirm for free:
function Restart-StaleService {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)]
[string]$ServiceName
)
if ($PSCmdlet.ShouldProcess($ServiceName, 'Restart service')) {
Restart-Service -Name $ServiceName
}
}
Restart-StaleService -ServiceName Spooler -WhatIf
# What if: Performing the operation "Restart service" on target "Spooler".
This pattern is the difference between a script run nervously once and a tool the whole team trusts.
Quick check
In this lab you will build Get-Greeting step by step, then evolve it into a proper infrastructure tool — culminating in a Restart-StaleService function with full -WhatIf support. Each step introduces one new concept.
Step 1 — Your first function
Define a function called Get-Greeting that emits the string 'Hello, ShellQuest!' when called, then call it. There is no return keyword needed — any unassigned expression is emitted to the pipeline.