Scripts#
A script (.ps1) is an entry point, not a home for logic. Keep scripts thin: parse input, call functions, report results. Anything reusable belongs in a function in a module.
Section structure#
A script file is laid out top to bottom in this order:
#Requiresstatements — PowerShell version and module dependencies with minimum versions.- Comment-based help —
.SYNOPSIS,.DESCRIPTION, and at least one.EXAMPLE. [CmdletBinding()]+param()— typed and validated, mandatory first; addSupportsShouldProcesswhen the script changes state.$ErrorActionPreference = 'Stop'.- Body — the thin orchestration.
#Requires -Version 7.0
#Requires -Modules Pester
<#
.SYNOPSIS
Rotate the automation secret and sync it to the target store.
.DESCRIPTION
Remove the current secret, create a replacement, and update the store that consumes it.
.EXAMPLE
./Rotate-Secret.ps1 -ValidityDays 365
#>
[CmdletBinding(SupportsShouldProcess)]
param(
# How long the new secret stays valid, in days.
[Parameter()]
[int] $ValidityDays = 180
)
$ErrorActionPreference = 'Stop'
# thin orchestration: call the functions that do the real work
Rules#
- Name scripts
Verb-Noun.ps1to match the function convention. - No side effects on load. A script runs top to bottom when invoked; it should not do work merely by being dot-sourced.
- Return objects, so the script composes in a pipeline like any other command.
Paths#
- Do not depend on the current directory. Avoid relative paths and
~— the meaning of~depends on the current PowerShell provider — and build paths from$PSScriptRootwithJoin-Path. - Pass full paths to .NET and native calls. .NET methods and external executables resolve relative paths against
[System.Environment]::CurrentDirectory, which PowerShell does not keep reliably in step with$PWD— it can lagSet-Location, and diverges in non-FileSystem providers (Registry,Cert:). Resolve to a full path first.