CodeToLive

PowerShell Functions & Modules

Functions allow you to encapsulate reusable code, while modules help organize and share your PowerShell components.

Basic Functions

# Simple function
function Get-Greeting {
    "Hello, PowerShell!"
}

# Calling the function
Get-Greeting

# Function with parameters
function Get-PersonalizedGreeting {
    param(
        [string]$Name,
        [int]$Age
    )
    "Hello $Name, you are $Age years old!"
}

Get-PersonalizedGreeting -Name "Alice" -Age 30

Advanced Functions

function Get-SystemInfo {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$ComputerName,
        
        [ValidateSet("CPU","Memory","Disk")]
        [string]$Component = "CPU",
        
        [switch]$Detailed
    )
    
    begin {
        Write-Verbose "Starting system info collection for $ComputerName"
    }
    
    process {
        switch ($Component) {
            "CPU" { 
                $info = Get-CimInstance Win32_Processor -ComputerName $ComputerName
                if ($Detailed) {
                    $info | Select-Object Name, NumberOfCores, MaxClockSpeed
                } else {
                    $info | Select-Object Name, LoadPercentage
                }
            }
            "Memory" { 
                Get-CimInstance Win32_PhysicalMemory -ComputerName $ComputerName |
                    Measure-Object -Property Capacity -Sum |
                    Select-Object @{Name="TotalGB";Expression={[math]::Round($_.Sum/1GB,2)}}
            }
            "Disk" { 
                Get-CimInstance Win32_LogicalDisk -ComputerName $ComputerName -Filter "DriveType=3" |
                    Select-Object DeviceID, @{Name="SizeGB";Expression={[math]::Round($_.Size/1GB,2)}}, 
                              @{Name="FreeGB";Expression={[math]::Round($_.FreeSpace/1GB,2)}}
            }
        }
    }
    
    end {
        Write-Verbose "Completed system info collection"
    }
}

# Using the advanced function
Get-SystemInfo -ComputerName "localhost" -Component Memory -Detailed
Get-SystemInfo -ComputerName "localhost" -Component Disk -Verbose

Parameter Attributes

Attribute Description Example
[Parameter()] Defines parameter behavior [Parameter(Mandatory=$true)]
[ValidateSet()] Restricts to specific values [ValidateSet("Low","Medium","High")]
[ValidateRange()] Restricts numeric range [ValidateRange(1,100)]
[ValidatePattern()] Regex validation [ValidatePattern("^[A-Z][a-z]+$")]
[ValidateScript()] Custom validation script [ValidateScript({Test-Path $_})]
[Alias()] Alternative parameter names [Alias("Server")]

Pipeline Input

function Process-Files {
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline=$true)]
        [System.IO.FileInfo]$File
    )
    
    process {
        [PSCustomObject]@{
            Name = $File.Name
            SizeKB = [math]::Round($File.Length/1KB,2)
            LastModified = $File.LastWriteTime
        }
    }
}

# Using pipeline input
Get-ChildItem -File | Process-Files | Sort-Object SizeKB -Descending

Error Handling in Functions

function Get-FileContent {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$Path
    )
    
    if (-not (Test-Path $Path)) {
        Write-Error "File not found: $Path"
        return
    }
    
    try {
        Get-Content -Path $Path -ErrorAction Stop
    }
    catch {
        Write-Error "Failed to read file: $_"
    }
}

Get-FileContent -Path "C:\nonexistent.txt"

Creating Modules

Module Structure

# Directory structure
# MyModule/
#   MyModule.psd1  # Module manifest
#   MyModule.psm1  # Root module file
#   Public/
#     Get-SystemInfo.ps1
#     Set-Configuration.ps1
#   Private/
#     HelperFunctions.ps1

Module Manifest (psd1)

@{
    ModuleVersion = '1.0'
    GUID = 'a1b2c3d4-e5f6-7890-g1h2-i3j4k5l6m7n8'
    Author = 'Your Name'
    Description = 'My PowerShell module'
    PowerShellVersion = '5.1'
    RootModule = 'MyModule.psm1'
    FunctionsToExport = @('Get-SystemInfo','Set-Configuration')
    PrivateData = @{
        PSData = @{
            Tags = @('System','Configuration')
            LicenseUri = 'https://opensource.org/licenses/MIT'
            ProjectUri = 'https://github.com/you/MyModule'
        }
    }
}

Root Module (psm1)

# Export module members
$publicFunctions = @(Get-ChildItem -Path "$PSScriptRoot\Public\*.ps1")
$privateFunctions = @(Get-ChildItem -Path "$PSScriptRoot\Private\*.ps1")

# Dot source all functions
foreach ($file in @($publicFunctions + $privateFunctions)) {
    try {
        . $file.FullName
    }
    catch {
        Write-Error "Failed to import function $($file.Name): $_"
    }
}

# Export only the public functions
Export-ModuleMember -Function $publicFunctions.BaseName

Module Management

# Import a module
Import-Module MyModule -Force

# List loaded modules
Get-Module

# Remove a module
Remove-Module MyModule

# Install from PowerShell Gallery
Install-Module -Name PSScriptAnalyzer -Scope CurrentUser -Force

# Update a module
Update-Module -Name PSScriptAnalyzer