HEMM Part 2: PowerShell Function Template for Reusable Scripts

🧠 TL;DR

You know how most of your old PowerShell scripts look different, have random parameters, and were clearly written at 2am after a fight with file share permissions? This fixes that. Here’s how to use a consistent PowerShell function template across your PowerShell module so you can stop rewriting the same boilerplate and start writing clean, repeatable code.

Overview

If you’re building a PowerShell module like HEMM (Hay-Ellis Master Module), consistency is everything. Reusable tools only stay reusable if they look, act, and feel the same. That means:

  • Parameters that behave predictably
  • Output that can be piped, logged, or counted
  • Comments that don’t make your eyes bleed

The solution? A function template. Use it. Copy it. Don’t argue with it, and even better automate it.

You can clone this from my git repo.

📦 The HEMM Template File

Here’s the exact template that ships with HEMM. It includes:

  • Standard headers for built-in help (Get-Help)
  • Common admin parameters like -Age, -File, and -Credential
  • Clean structure with room for logic
<#
.SYNOPSIS
    One-line summary of what this function does.

.DESCRIPTION
    More detailed explanation, use cases, and what it helps with.

.PARAMETER Age
    Number of days to use for filtering (e.g., inactive objects).

.PARAMETER File
    If set, results are saved to a file in the OutputFiles folder.

.PARAMETER Count
    If set, outputs the total count of results.

.PARAMETER Domain
    The domain to target (default: Hay-Ellis.Local).

.PARAMETER Credential
    Optional credentials to run the query.

.EXAMPLE
    Get-Something -Age 90 -File -Count

.NOTES
    Author   : Ashley Hay-Ellis  
    Version  : 1.0  
    License  : MIT  
    Change History:
        2024-07-03 – Initial release
#>

function Get-Something {
    [CmdletBinding()]
    param (
        [int]$Age = 180,  # Default: 180 days
        [switch]$File,    # Use as -File (true if present)
        [switch]$Count,   # Use as -Count (true if present)
        [string]$Domain = "Hay-Ellis.Local",
        [pscredential]$Credential
    )

    # Import the Active Directory module
    Import-Module ActiveDirectory

    $inactiveDate = (Get-Date).AddDays(-$age)

    #sets the date
    $OutFileDate = Get-date -Format "yyyy_MM_dd_HHmmss"

    #Specify the path for the output CSV file
    $outputFilePath = ".\OutputFiles\*filenamesomething*_${OutFileDate}.txt"


    if ($file -eq $true) {
        #write data to output
        write-host "Exported to file ${outputFilePath}" -ForegroundColor Green
    }else{
        #write data to screen only
        
    }
}

The idea is to keep your functions “drop-in friendly”. These params are used across multiple functions, so passing them around is easy:

ParameterWhy it’s useful
-AgeFor age-based filtering (e.g. inactive accounts)
-FileOptional file output for automation or review
-CountQuick metrics without extra logic
-DomainMakes functions domain-aware by default
-CredentialRun functions with alt creds without rewriting auth logic

This is especially powerful when chaining or wrapping functions. If every function understands the same core parameters, they can pass them downstream — no extra boilerplate needed.

Obviously you can add your own parameters. I would recommend just adding them to your own template file.

🚀 Using the Template to Start a New Script

Here’s your workflow:

  1. Copy the template from .\common\FunctionTemplate.ps1
  2. Rename Get-Something to your actual function name (e.g. Get-EmptyOUs)
  3. Update the header: .SYNOPSIS, .DESCRIPTION, and .EXAMPLE
  4. Replace the placeholder logic with your real code
  5. Profit

📎 Pro tip: Checkout Part 3 for an automated Functions Template.

🧾 Example

Let’s say you’re writing a function to get disabled users older than X days. Start with the template, tweak the logic, and boom — job done. The output can be piped, logged, or counted just by reusing the built-in params.

Get-DisabledUsers -Age 90 -File -Count -Domain "corp.local"

One command, predictable output, no extra flags to memorize.

✅ Final Thoughts

Templates are boring until you don’t use one — then they’re a mess to fix later. If you’re building a real-world toolkit (not just a one-off script), start with a consistent function template. Build smart now, automate more later.

Leave a Reply

Your email address will not be published. Required fields are marked *