PowerShell Functions

A function is a named, reusable block of code. Instead of writing the same logic multiple times throughout a script, a function packages that logic under a name — and that name can be called whenever the logic is needed. Functions make scripts shorter, easier to read, and simpler to maintain.

Why Use Functions?

  Without Functions                    With Functions
  ----------------------               ----------------------
  # Script repeats code                function Get-DiskStatus {
  $drive = Get-PSDrive C                   $drive = Get-PSDrive C
  $freeGB = $drive.Free / 1GB              $drive.Free / 1GB
  Write-Host "Free: $freeGB"           }
  
  # Repeated 10 times in script        # Called once, used 10 times
  ...                                  Get-DiskStatus

Basic Function Syntax


function FunctionName {
    # Code block
}

Simple Function


function Say-Hello {
    Write-Host "Hello from PowerShell!"
}

# Call the function
Say-Hello

Output:


Hello from PowerShell!

Function with Parameters

Parameters let functions accept input values. This makes functions flexible and reusable.


function Greet-User {
    param (
        $Name
    )
    Write-Host "Hello, $Name! Welcome to eStudy247."
}

# Call with argument
Greet-User -Name "Ananya"
Greet-User -Name "Kiran"

Output:


Hello, Ananya! Welcome to eStudy247.
Hello, Kiran! Welcome to eStudy247.

Function with Multiple Parameters


function Add-Numbers {
    param (
        $Number1,
        $Number2
    )
    $sum = $Number1 + $Number2
    Write-Host "$Number1 + $Number2 = $sum"
}

Add-Numbers -Number1 15 -Number2 25
Add-Numbers -Number1 100 -Number2 300

Output:


15 + 25 = 40
100 + 300 = 400

Function with Default Parameter Values


function Send-Greeting {
    param (
        $Name    = "Guest",
        $Message = "Welcome!"
    )
    Write-Host "$Message, $Name"
}

# With arguments
Send-Greeting -Name "Priya" -Message "Good morning"

# Without arguments – uses defaults
Send-Greeting

Output:


Good morning, Priya
Welcome!, Guest

Returning Values from a Function

A function returns a value using the return keyword (or by simply producing output in the last statement).


function Get-SquareRoot {
    param ($Number)
    $result = [math]::Sqrt($Number)
    return $result
}

$root = Get-SquareRoot -Number 144
Write-Host "Square root of 144 is: $root"

Output:


Square root of 144 is: 12

Implicit Return (No return Keyword)


function Get-FullName {
    param ($FirstName, $LastName)
    "$FirstName $LastName"    # This line's output becomes the return value
}

$name = Get-FullName -FirstName "Arjun" -LastName "Sharma"
Write-Host "Full name: $name"

Output:


Full name: Arjun Sharma

Returning Multiple Values


function Get-Stats {
    param ($Numbers)
    
    $min = ($Numbers | Measure-Object -Minimum).Minimum
    $max = ($Numbers | Measure-Object -Maximum).Maximum
    $avg = ($Numbers | Measure-Object -Average).Average
    
    return @{
        Min = $min
        Max = $max
        Avg = [math]::Round($avg, 2)
    }
}

$data   = @(10, 45, 23, 88, 56, 72)
$result = Get-Stats -Numbers $data

Write-Host "Min: $($result.Min)"
Write-Host "Max: $($result.Max)"
Write-Host "Avg: $($result.Avg)"

Output:


Min: 10
Max: 88
Avg: 49

Advanced Function with [CmdletBinding]

Adding [CmdletBinding()] to a function makes it behave like a proper PowerShell cmdlet. It unlocks built-in parameters like -Verbose, -Debug, and -WhatIf.


function Remove-TempFiles {
    [CmdletBinding(SupportsShouldProcess=$true)]
    param (
        [string]$FolderPath
    )

    $files = Get-ChildItem -Path $FolderPath -Filter "*.tmp"

    foreach ($file in $files) {
        if ($PSCmdlet.ShouldProcess($file.FullName, "Delete")) {
            Remove-Item -Path $file.FullName -Force
            Write-Verbose "Deleted: $($file.Name)"
        }
    }
}

# Dry run with -WhatIf
Remove-TempFiles -FolderPath "C:\Temp" -WhatIf

# Verbose output
Remove-TempFiles -FolderPath "C:\Temp" -Verbose

Typed Parameters

Specifying parameter types enforces the correct data type and gives better error messages.


function Get-CircleArea {
    param (
        [double]$Radius
    )
    $area = [math]::PI * $Radius * $Radius
    return [math]::Round($area, 4)
}

$area = Get-CircleArea -Radius 5
Write-Host "Area of circle: $area"

Output:


Area of circle: 78.5398

Mandatory Parameters


function Get-UserInfo {
    param (
        [Parameter(Mandatory=$true)]
        [string]$Username,

        [string]$Domain = "local"
    )
    Write-Host "Looking up: $Username@$Domain"
}

# This will prompt for Username if not provided
Get-UserInfo -Username "admin"
Get-UserInfo -Username "ravi" -Domain "company.com"

Output:


Looking up: admin@local
Looking up: ravi@company.com

Recursive Function

A recursive function calls itself. A classic example is calculating a factorial.


function Get-Factorial {
    param ([int]$n)

    if ($n -le 1) {
        return 1
    }
    return $n * (Get-Factorial -n ($n - 1))
}

Write-Host "5! = $(Get-Factorial -n 5)"    # 120
Write-Host "6! = $(Get-Factorial -n 6)"    # 720

Output:


5! = 120
6! = 720

Function Scope


$globalVar = "I am global"

function Test-Scope {
    $localVar  = "I am local"
    Write-Host $globalVar   # Accessible – global scope
    Write-Host $localVar    # Accessible – local scope
}

Test-Scope

Write-Host $globalVar       # Accessible
Write-Host $localVar        # Error – $localVar not accessible outside function

Real-World Example – Log Writer Function


function Write-Log {
    param (
        [string]$Message,
        [string]$Level = "INFO",
        [string]$LogFile = "C:\Logs\app.log"
    )

    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry  = "[$timestamp] [$Level] $Message"

    Write-Host $logEntry

    # Also write to log file
    Add-Content -Path $LogFile -Value $logEntry
}

Write-Log -Message "Script started"
Write-Log -Message "Processing data..." -Level "DEBUG"
Write-Log -Message "An error occurred" -Level "ERROR"

Output:


[2026-03-21 10:30:00] [INFO] Script started
[2026-03-21 10:30:01] [DEBUG] Processing data...
[2026-03-21 10:30:02] [ERROR] An error occurred

Summary

Functions eliminate code repetition and make scripts modular and maintainable. Parameters accept input. Default values handle optional arguments. The return keyword sends output back to the caller. Adding [CmdletBinding()] promotes a function to a full cmdlet with built-in switches like -WhatIf and -Verbose. Mandatory parameters force callers to supply critical values. Recursive functions solve problems that naturally repeat in smaller sub-steps. Together, these features make PowerShell functions as powerful as functions in any modern scripting language.

Leave a Comment