Tools#
The PowerShell toolchain is more uniform than zsh / bash. One
interpreter (pwsh), one linter (PSScriptAnalyzer), one
test framework (Pester), one language server. The operator
mostly picks editors and CI hosts.
Interpreter#
pwsh, PowerShell 7+, cross-platform, .NET-backed. The current line.powershell, Windows PowerShell 5.1, Windows-only, .NET Framework. Legacy; still shipped with Windows.
Check the version.
$PSVersionTable
Useful invocation flags.
Flag |
Effect |
|---|---|
|
Run a script and exit |
|
Run an expression and exit |
|
Skip |
|
Skip the banner |
|
Disallow prompts; fail fast in automation |
|
Run unsigned scripts (Windows; default-deny otherwise) |
$ pwsh -NoProfile -File ./script.ps1
$ pwsh -NoProfile -Command 'Get-Process | Select-Object -First 3'
Linting#
PSScriptAnalyzer, the standard PowerShell linter. Catches unapproved verbs, alias usage, missing
[CmdletBinding()], parameter validation gaps. CI gate of choice.
Install-Module PSScriptAnalyzer -Scope CurrentUser
Invoke-ScriptAnalyzer -Path ./script.ps1
Invoke-ScriptAnalyzer -Path ./Module -Recurse -Severity Error,Warning
Invoke-ScriptAnalyzer -Path ./Module -Settings PSGallery
Most projects ship a PSScriptAnalyzerSettings.psd1 with the
rule set the team has agreed on.
@{
IncludeRules = @('PSAvoidUsingCmdletAliases',
'PSAvoidUsingWriteHost',
'PSUseConsistentIndentation')
ExcludeRules = @()
Rules = @{
PSUseConsistentIndentation = @{
IndentationSize = 4
Kind = 'space'
}
}
}
Formatting#
PSScriptAnalyzer ships Invoke-Formatter for the formatting
rules. It is the closest thing to a PowerShell shfmt.
$code = Get-Content ./script.ps1 -Raw
Invoke-Formatter -ScriptDefinition $code |
Set-Content ./script.ps1
Testing#
Pester, the de-facto BDD test framework.
Install-Module Pester -Scope CurrentUser
Invoke-Pester ./tests
Invoke-Pester ./tests -Output Detailed -CodeCoverage './module/*.ps1'
Debugging#
PowerShell ships a usable debugger built into the host.
Set-PSBreakpoint -Script script.ps1 -Line 42Set-PSBreakpoint -Command Get-Thing(break when a name is called)Set-PSBreakpoint -Variable foo -Mode WriteDebug-Job,Debug-Process,Debug-Runspace, attach to a running script.
Inline.
Wait-Debugger # like a breakpoint;
# drops into the debugger
In VS Code (with the PowerShell extension), F5 launches the debugger directly; gutter clicks set breakpoints.
Trace.
Set-PSDebug -Trace 2 # trace each statement
Set-PSDebug -Off
For per-call timing.
Measure-Command { Get-LargeFiles -Path . -MinKB 500 }
Profiling#
No bundled profiler. The standard reach is:
Measure-Command { ./script.ps1 }
# per-step, with PSScriptAnalyzer-style trace
Trace-Command -Name ParameterBinding -Expression { Get-Process } -PSHost
Editing#
PowerShell extension for VS Code, LSP, debugger, Pester integration, snippets. The default authoring environment.
Editor Services, the language server, also used by Neovim, Sublime, Emacs.
ISE, the legacy Windows-only PowerShell ISE. Frozen at PowerShell 5.1; do not target for new work.
CI Integration#
PowerShell on the runner. The standard pattern.
# GitHub Actions
- shell: pwsh
run: |
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
Invoke-Pester -Output Detailed -CI
Invoke-ScriptAnalyzer -Path ./Module -Recurse `
-Severity Error -EnableExit