PowerShell Parameters: Advanced Function Parameters Guide

PowerShell Parameters: Advanced Function Parameters Guide

PowerShell Tips Editor 3 min read
PowerShell Parameters: Advanced Function Parameters Guide

A function without parameter validation is an accident waiting to happen — wrong value, wrong type, no error until something fails deep in the logic. PowerShell function parameters with validation attributes, parameter sets, and pipeline binding turn a basic function into a self-documenting, self-validating tool that’s as safe to call as a built-in cmdlet. This post covers every advanced parameter feature with practical examples for each.

Mandatory Parameters

Mark a parameter with [Parameter(Mandatory)] to require it at call time. If the caller omits it, PowerShell prompts interactively — or throws a non-interactive error in scripts. Mandatory parameters should have no default value.

function Send-Alert {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$To,

        [Parameter(Mandatory)]
        [string]$Message,

        [string]$Subject = "Automated Alert"  # Optional with default
    )

    Write-Output "Sending to $To: $Subject — $Message"
}

Send-Alert -To "[email protected]" -Message "Disk full"
# Send-Alert -Message "test"  # Prompts for -To

Default Values

Optional parameters have default values assigned in the parameter declaration. Defaults apply when the parameter is not supplied by the caller.

function Get-LogEntries {
    [CmdletBinding()]
    param(
        [string]$LogPath    = "C:\Logs\app.log",
        [int]$LastN         = 100,
        [string]$Level      = "ERROR",
        [datetime]$Since    = (Get-Date).AddDays(-1)
    )

    Write-Output "Reading $LastN entries from $LogPath since $($Since.ToString('yyyy-MM-dd'))"
}

Get-LogEntries                                   # Uses all defaults
Get-LogEntries -LastN 500 -Level "WARN"         # Overrides two defaults

ValidateSet for Allowed Values

[ValidateSet()] restricts a parameter to a predefined list of values. PowerShell validates at call time and provides tab completion for the allowed values — no manual validation code needed.

function Deploy-App {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$AppName,

        [Parameter(Mandatory)]
        [ValidateSet("Development", "Staging", "Production")]
        [string]$Environment
    )

    Write-Output "Deploying $AppName to $Environment"
}

Deploy-App -AppName "WebAPI" -Environment "Staging"
# Deploy-App -AppName "WebAPI" -Environment "QA"  # ERROR: invalid value
Deploying WebAPI to Staging

ValidateRange and ValidatePattern

[ValidateRange(min, max)] enforces numeric bounds. [ValidatePattern("regex")] validates string format against a regex. Both throw a parameter validation error at call time if the value doesn’t meet the constraint.

function Set-RetentionDays {
    [CmdletBinding()]
    param(
        [ValidateRange(1, 365)]
        [int]$Days = 30,

        [ValidatePattern("^[A-Z]{2,5}$")]
        [string]$PolicyCode
    )

    Write-Output "Retention: $Days days, Policy: $PolicyCode"
}

Set-RetentionDays -Days 90 -PolicyCode "GDPR"
# Set-RetentionDays -Days 400  # ERROR: 400 is outside 1-365
# Set-RetentionDays -Days 30 -PolicyCode "lowercase"  # ERROR: fails pattern

Parameter Sets

Parameter sets let you define mutually exclusive groups of parameters — like -ComputerName (for remote) vs -Session (for reuse). Each set must be distinguishable by at least one unique mandatory parameter.

function Connect-Target {
    [CmdletBinding(DefaultParameterSetName = "ByName")]
    param(
        [Parameter(Mandatory, ParameterSetName = "ByName")]
        [string]$ComputerName,

        [Parameter(ParameterSetName = "ByName")]
        [System.Management.Automation.PSCredential]$Credential,

        [Parameter(Mandatory, ParameterSetName = "BySession")]
        [System.Management.Automation.Runspaces.PSSession]$Session
    )

    Write-Output "Using parameter set: $($PSCmdlet.ParameterSetName)"
    if ($PSCmdlet.ParameterSetName -eq "ByName") {
        Write-Output "Connecting to: $ComputerName"
    } else {
        Write-Output "Using existing session"
    }
}

Set DefaultParameterSetName on [CmdletBinding()] to avoid ambiguity errors when no mandatory parameters are provided.

Pipeline Input with ValueFromPipeline

Enable pipeline binding with ValueFromPipeline or ValueFromPipelineByPropertyName. When accepting pipeline input, wrap the body in a process block so each piped item is handled individually.

function Test-HostAvailability {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
        [string]$ComputerName
    )

    process {
        [PSCustomObject]@{
            ComputerName = $ComputerName
            Online       = (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet)
        }
    }
}

# Pipeline input — processes each server individually
"server01", "server02", "server03" | Test-HostAvailability

# Also works with direct parameter
Test-HostAvailability -ComputerName "server01"

Common Errors and Fixes

  • Parameter sets require DefaultParameterSetName to avoid ambiguity: If you define multiple parameter sets but don’t set DefaultParameterSetName on [CmdletBinding()], PowerShell may throw an “Ambiguous parameter set” error when the caller omits all mandatory parameters. Always specify a default set even if you think callers will always supply required parameters.
  • Pipeline binding requires process{} block: Without a process {} block, a function with ValueFromPipeline only processes the last piped item — all previous items are silently discarded. The begin {} block runs once before any pipeline input; process {} runs once per item; end {} runs once after all items are processed. For pipeline-enabled functions, the body must go in process {}.

Related Cmdlets / See Also

Wrapping Up

Advanced parameter validation transforms functions from flexible-but-fragile to robust-and-self-documenting. ValidateSet and ValidateRange are the highest-value attributes to add first — they eliminate an entire class of input validation bugs with one line. As a next step, add [CmdletBinding()] and appropriate validation attributes to the three most-called functions in your current scripts.

Send-Item -To