PowerShell Comment-Based Help: Document Your Functions

PowerShell Comment-Based Help: Document Your Functions

PowerShell Tips Editor 3 min read
PowerShell Comment-Based Help: Document Your Functions

Writing a function that only you understand today is a liability tomorrow. PowerShell comment-based help transforms your functions into self-documenting tools that respond to Get-Help just like built-in cmdlets do. When a colleague — or future you — runs Get-Help Send-AlertEmail -Full, they get accurate parameter descriptions, usage examples, and expected inputs and outputs, all sourced directly from the code file. This post covers every comment-based help keyword, correct placement, and how to verify your help renders correctly.

Help Block Placement

PowerShell recognizes comment-based help in two locations: immediately inside the function body (before any other code) or immediately above the function keyword with no blank lines between the block and the keyword. Either position works, but placing the block inside the function is the most common convention and keeps the help bundled with the function if you copy it elsewhere.

# Pattern 1: Inside the function body (recommended)
function Get-DiskReport {
    <#
    .SYNOPSIS
        Returns disk usage for one or more computers.
    #>
    param([string[]]$ComputerName)
    # ... function body
}

# Pattern 2: Immediately above the function keyword
<#
.SYNOPSIS
    Returns disk usage for one or more computers.
#>
function Get-DiskReport {
    param([string[]]$ComputerName)
}

.SYNOPSIS and .DESCRIPTION

.SYNOPSIS is a one-line summary shown in compact Get-Help output. Keep it under 80 characters. .DESCRIPTION is the long-form explanation — use it to explain why someone would call the function, any prerequisites, and behavioral nuances.

function Invoke-LogRotation {
    <#
    .SYNOPSIS
        Archives and deletes log files older than a specified age.

    .DESCRIPTION
        Invoke-LogRotation moves log files older than -AgeDays from the source
        folder to an archive path, then removes files in the archive older than
        -ArchiveAgeDays. Requires write access to both paths. Designed to run
        as a scheduled task on Windows Server log directories.
    #>
    param(
        [string]$LogPath   = 'C:\Logs',
        [int]$AgeDays      = 30,
        [string]$Archive   = 'C:\Logs\Archive',
        [int]$ArchiveAgeDays = 90
    )
}

.PARAMETER Documentation

Each parameter gets its own .PARAMETER block. The name on the .PARAMETER line must exactly match the parameter name — case-insensitively but character-for-character, no extra spaces. The description follows on the next line.

    .PARAMETER LogPath
        The folder containing log files to rotate. Defaults to C:\Logs.

    .PARAMETER AgeDays
        Log files older than this many days are moved to the archive. Default: 30.

    .PARAMETER Archive
        Destination folder for archived log files. Created if it does not exist.

    .PARAMETER ArchiveAgeDays
        Files in the archive older than this many days are permanently deleted. Default: 90.

.EXAMPLE with Output

At least one .EXAMPLE block is essential. PowerShell help displays examples with syntax highlighting in the terminal. Show the command on the first line (no prompt symbol) and annotate the output on subsequent lines:

    .EXAMPLE
        Invoke-LogRotation -LogPath 'C:\IIS\Logs' -AgeDays 14

        Rotates IIS logs older than 14 days, using the default archive path and
        archive retention of 90 days.

    .EXAMPLE
        Invoke-LogRotation -LogPath '\\server\app\logs' -AgeDays 7 -Archive '\\nas\archive\app'

        Rotates logs on a UNC share, sending archived files to a NAS path.

.INPUTS and .OUTPUTS

.INPUTS describes what the function accepts from the pipeline. .OUTPUTS describes what it emits. Both accept free text, but mirroring the .NET type name is the convention:

    .INPUTS
        System.String
        You can pipe a path string to the -LogPath parameter.

    .OUTPUTS
        System.Management.Automation.PSCustomObject
        Returns one object per processed folder with properties: Path, FilesRotated, BytesFreed.

Testing Your Help Output

After writing the help block, dot source the file and run Get-Help with different detail levels to verify the output:

. .\Invoke-LogRotation.ps1

# Summary view
Get-Help Invoke-LogRotation

# Full detail including examples
Get-Help Invoke-LogRotation -Full

# Examples only
Get-Help Invoke-LogRotation -Examples

# Parameter-specific help
Get-Help Invoke-LogRotation -Parameter AgeDays
NAME
    Invoke-LogRotation

SYNOPSIS
    Archives and deletes log files older than a specified age.

SYNTAX
    Invoke-LogRotation [[-LogPath] <String>] [[-AgeDays] <Int32>] ...

Common Errors and Fixes

  • Help block must be inside function or directly above it. A blank line between a help block and the function keyword breaks association — PowerShell treats it as a standalone comment, not function help. Check for trailing blank lines.
  • Missing period before keyword breaks parsing. Every keyword — .SYNOPSIS, .PARAMETER, .EXAMPLE — requires the leading dot. Omitting it makes PowerShell treat that line as help body text, merging it into the previous section rather than starting a new one.

Related Cmdlets / See Also

Wrapping Up

Comment-based help costs five minutes to write and pays dividends every time someone — including you — needs to recall what a function does six months later. Get .SYNOPSIS, .PARAMETER, and at least one .EXAMPLE block into every function you write, verify with Get-Help -Full, and your scripts become genuinely self-documenting tools.

Send-Item -To