Skip to content

Function Parameters

Note

A complete reference for PowerShell function parameters — from basic declarations to advanced validation, parameter sets, and pipeline binding.

Overview

Parameters are how you pass data into functions and scripts. PowerShell's parameter system is one of its most powerful features — it handles type checking, validation, tab completion, and pipeline binding automatically once you declare it correctly.

This page covers the full parameter system. For a broader introduction to functions, see Functions.

The param() Block

All parameters live inside a param() block at the top of your function or script:

function Get-Report {
    param(
        [string]$ComputerName,
        [int]$DaysBack = 7,
        [switch]$IncludeArchived
    )

    # Function body
}

Rules:

  • param() must be the first executable statement in the function
  • Each parameter is separated by a comma
  • Attributes stack above the parameter, one per line

Data Types

Declaring a type forces PowerShell to validate and convert input automatically:

param(
    [string]$Name,          # Text
    [int]$Count,            # Whole number
    [double]$Threshold,     # Decimal number
    [bool]$IsEnabled,       # True/False (prefer [switch] for flags — see below)
    [datetime]$StartDate,   # Date and time
    [string[]]$Servers,     # Array of strings
    [hashtable]$Config,     # Key-value pairs
    [scriptblock]$Action    # A block of code
)

If the caller passes the wrong type and PowerShell can't convert it, you get a clear error immediately — before your function body runs.

Parameter Attributes

Attributes go inside [Parameter(...)] on the line above the type declaration:

param(
    [Parameter(Mandatory=$true, Position=0, HelpMessage="Enter the server name")]
    [string]$ServerName
)

Mandatory

Forces the caller to provide a value. If omitted, PowerShell prompts interactively:

param(
    [Parameter(Mandatory=$true)]
    [string]$Username,

    [string]$Domain = "CORP"   # Optional — has a default
)

Use Mandatory=$true on parameters that have no safe default. Leave it off (or use Mandatory=$false) for anything optional.

Position

Lets the caller pass values without naming the parameter:

function Copy-File {
    param(
        [Parameter(Position=0)]
        [string]$Source,

        [Parameter(Position=1)]
        [string]$Destination
    )
}

# Both of these work:
Copy-File "C:\file.txt" "D:\backup\"
Copy-File -Source "C:\file.txt" -Destination "D:\backup\"

Named parameters are always clearer in scripts; positional is handy for quick interactive use.

HelpMessage

Shown when PowerShell prompts the user for a missing Mandatory parameter:

param(
    [Parameter(Mandatory=$true, HelpMessage="Enter the target computer name (e.g. PC-001)")]
    [string]$ComputerName
)

When prompted, type !? to see the help message.

ValueFromPipeline

Lets the parameter receive objects piped into the function:

function Get-DiskInfo {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline=$true)]
        [string]$ComputerName
    )

    process {
        Get-PSDrive -PSProvider FileSystem -ComputerName $ComputerName
    }
}

"Server01", "Server02", "Server03" | Get-DiskInfo

Important

You need a process {} block when using ValueFromPipeline, otherwise only the last piped item is processed.

ValueFromPipelineByPropertyName

Binds a pipeline object's property to this parameter by matching the property name:

function Restart-TargetService {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipelineByPropertyName=$true)]
        [string]$Name   # Matches the .Name property on service objects
    )

    process {
        Restart-Service -Name $Name -WhatIf
    }
}

# The Name property on Get-Service output binds automatically
Get-Service -Name "Spooler", "WinRM" | Restart-TargetService

Parameter Aliases

[Alias()] lets callers use a shorthand name for a parameter:

param(
    [Alias('cn', 'Computer')]
    [string]$ComputerName,

    [Alias('d')]
    [int]$DaysBack = 30
)

# All of these are equivalent:
Get-Report -ComputerName "Server01"
Get-Report -Computer "Server01"
Get-Report -cn "Server01"

Useful for backward compatibility when you rename a parameter, or just for convenience at the prompt.

Validation Attributes

Validation attributes reject bad input before your function body runs. PowerShell shows a clear error with the parameter name and what was wrong.

ValidateSet

Restricts input to a fixed list of allowed values. Also enables tab completion — callers can tab through the valid options:

param(
    [ValidateSet("Development", "Staging", "Production")]
    [string]$Environment
)
# Works
Set-Config -Environment "Production"

# Fails immediately with a clear error
Set-Config -Environment "Prod"
# Cannot validate argument on parameter 'Environment'. The argument "Prod" does not
# belong to the set "Development,Staging,Production"...

Case-insensitive by default. Pass IgnoreCase=$false to enforce exact case:

[ValidateSet("Start", "Stop", IgnoreCase=$false)]

ValidatePattern

Validates input against a regular expression:

param(
    [ValidatePattern('^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$')]
    [string]$IPAddress,

    [ValidatePattern('^[A-Z]{2,5}-\d{4}$')]
    [string]$TicketNumber   # e.g. "INC-1234" or "CHANGE-9901"
)

The error message just says the pattern didn't match. If you need a friendlier message, use ValidateScript instead.

ValidateScript

Custom validation using any PowerShell expression. The $_ variable holds the incoming value. Return $true to pass, throw to fail with a custom message:

param(
    [ValidateScript({
        if (Test-Path $_) { $true }
        else { throw "Path '$_' does not exist." }
    })]
    [string]$LogPath,

    [ValidateScript({
        if ($_ -gt (Get-Date)) { $true }
        else { throw "Date must be in the future." }
    })]
    [datetime]$ScheduledDate
)

ValidateScript is the most flexible validator — use it when the other validators can't express the rule.

ValidateRange

Constrains a numeric value to a min/max (inclusive):

param(
    [ValidateRange(1, 100)]
    [int]$Percentage,

    [ValidateRange(0, 65535)]
    [int]$Port = 8080
)

PowerShell 6+ also accepts named ranges:

[ValidateRange("Positive")]     # Greater than 0
[ValidateRange("NonNegative")]  # 0 or greater
[ValidateRange("Negative")]     # Less than 0
[ValidateRange("NonPositive")]  # 0 or less

ValidateLength

Constrains a string to a minimum and maximum character count:

param(
    [ValidateLength(3, 15)]
    [string]$Username,

    [ValidateLength(8, 128)]
    [string]$Password
)

ValidateCount

Constrains how many elements an array parameter can receive:

param(
    [ValidateCount(1, 5)]
    [string[]]$Servers   # Must provide between 1 and 5 server names
)

ValidateNotNull

Rejects $null but allows empty strings:

param(
    [ValidateNotNull()]
    [object]$InputData
)

ValidateNotNullOrEmpty

Rejects both $null and empty strings — the one you'll reach for most often:

param(
    [ValidateNotNullOrEmpty()]
    [string]$ServerName
)

Switch Parameters

[switch] is a flag — present means $true, absent means $false. No value needed from the caller:

function Export-Report {
    param(
        [string]$OutputPath = "C:\Reports",
        [switch]$IncludeArchived,
        [switch]$AsCSV,
        [switch]$Force
    )

    if ($IncludeArchived) {
        # pull in archived records
    }

    if ($AsCSV) {
        # change output format
    }
}

# Caller includes only the flags they want
Export-Report -IncludeArchived -Force
Export-Report -AsCSV
Export-Report   # all switches are false

Test a switch in conditions like a boolean — no need to compare it to $true.

Parameter Sets

Parameter sets let you define mutually exclusive groups of parameters — like how Get-Process takes either a name or a process ID, but not both as mandatory at the same time:

function Find-User {
    [CmdletBinding(DefaultParameterSetName="ByUsername")]
    param(
        [Parameter(Mandatory=$true, ParameterSetName="ByUsername")]
        [string]$Username,

        [Parameter(Mandatory=$true, ParameterSetName="ByEmail")]
        [string]$Email,

        [Parameter(Mandatory=$true, ParameterSetName="ByID")]
        [int]$UserID,

        # Shared across all sets — repeat the attribute for each set
        [Parameter(ParameterSetName="ByUsername")]
        [Parameter(ParameterSetName="ByEmail")]
        [Parameter(ParameterSetName="ByID")]
        [switch]$IncludeGroups
    )

    switch ($PSCmdlet.ParameterSetName) {
        "ByUsername" { Write-Output "Searching by username: $Username" }
        "ByEmail"    { Write-Output "Searching by email: $Email" }
        "ByID"       { Write-Output "Searching by ID: $UserID" }
    }
}

# Each call uses a different set — they're mutually exclusive
Find-User -Username "jdoe"
Find-User -Email "jdoe@corp.com"
Find-User -UserID 1042

$PSCmdlet.ParameterSetName tells you which set was active at runtime. Requires [CmdletBinding()].

Combining Validators and Attributes

Stack as many attributes as needed — they all apply:

function Set-ServerConfig {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true, Position=0, HelpMessage="Server hostname or IP")]
        [ValidateNotNullOrEmpty()]
        [Alias('cn', 'Server')]
        [string]$ComputerName,

        [Parameter(Mandatory=$true)]
        [ValidateSet("Web", "Database", "Cache", "Queue")]
        [string]$Role,

        [ValidateRange(1, 65535)]
        [int]$Port = 443,

        [switch]$Restart
    )

    Write-Output "Configuring $ComputerName as $Role on port $Port"
}

Quick Reference

Attribute / Validator What it does
Mandatory=$true Caller must provide a value
Position=0 Parameter can be passed positionally
HelpMessage="..." Shown when prompting for mandatory input
ValueFromPipeline=$true Accepts pipeline input
ValueFromPipelineByPropertyName=$true Binds matching property name from pipeline objects
[Alias('x')] Shorthand name for the parameter
[ValidateSet(...)] Fixed list of allowed values + tab completion
[ValidatePattern('regex')] Regex match required
[ValidateScript({...})] Custom logic — return $true or throw
[ValidateRange(min, max)] Numeric range constraint
[ValidateLength(min, max)] String character count constraint
[ValidateCount(min, max)] Array element count constraint
[ValidateNotNull()] Rejects $null
[ValidateNotNullOrEmpty()] Rejects $null and empty strings
[switch] Flag parameter — present = true, absent = false
ParameterSetName="..." Groups mutually exclusive parameters
  • Functions - Function structure, return values, and advanced function patterns
  • Script Structure - Using parameters in scripts (not just functions)
  • Comment-Based Help - Documenting your parameters with .PARAMETER help blocks