PowerShell is a task automation and configuration management framework from Microsoft, consisting of a command-line shell and associated scripting language built on .NET. PowerShell helps system administrators and power-users rapidly automate tasks that manage operating systems and processes.
PowerShell Anti-Patterns Overview
Using Invoke-Expression Unnecessarily
Invoke-Expression
(or its alias iex
) when possible, especially with user input or external data. It can lead to code injection vulnerabilities. Use parameters, splatting, or the call operator (&
) instead.Not Using Proper Error Handling
try/catch
blocks or the -ErrorAction
and -ErrorVariable
parameters. This helps you handle errors gracefully and provide meaningful feedback to users.Using Select-String Instead of Regex Methods
-match
operator or regex methods instead of Select-String
for simple pattern matching in strings. Select-String
is designed for searching through files or collections of strings, not for simple string operations.Using ForEach-Object in a Pipeline Unnecessarily
ForEach-Object
(or its alias %
) when simpler alternatives exist. For property extraction, use Select-Object -ExpandProperty
or direct property access. ForEach-Object
is slower and more verbose for simple operations.Not Using the Pipeline Effectively
Using Write-Host Instead of Write-Output
Write-Output
(or simply let PowerShell implicitly output objects) for data that might be consumed by other commands in a pipeline. Use Write-Host
only for visual feedback that isn’t meant to be processed further.Not Using Parameter Validation
Using String Concatenation Instead of Format Strings
-f
), or [string]::Format()
instead of string concatenation. These methods are more readable and efficient, especially for complex strings.Not Using Strong Types
Using Aliases in Scripts
gps
, ?
, %
, sort
, select
) in scripts and functions. Use full command and parameter names for better readability, maintainability, and to avoid issues if aliases change or aren’t available in all environments.Not Using PSCustomObject for Structured Data
[PSCustomObject]
for structured data instead of hashtables or arrays. It provides better property access syntax, works well with the pipeline, and is more idiomatic in PowerShell.Not Using Appropriate Scopes
$script:
, $local:
, $private:
) to limit variable visibility.Not Using Begin/Process/End Blocks in Advanced Functions
begin
, process
, and end
blocks in advanced functions that accept pipeline input. The process
block runs once for each pipeline object, while begin
and end
run once before and after processing.Not Using CmdletBinding
[CmdletBinding()]
for your functions to make them behave more like cmdlets. This gives you access to common parameters like -Verbose
, -Debug
, and -ErrorAction
, and enables better error handling and parameter validation.Using Write-Debug or Write-Verbose Without Checking Preferences
[CmdletBinding()]
when using Write-Verbose
or Write-Debug
. This ensures that these messages are only displayed when the corresponding preference variables are set or when the -Verbose
or -Debug
switches are used.Not Using Appropriate Output Types
[OutputType()]
to specify the type of objects your function returns. This helps with documentation, IntelliSense, and makes your code more self-documenting.Not Using Proper Module Structure
Not Using Proper Comment-Based Help
Get-Help
cmdlet and makes your code more maintainable.Using Invoke-WebRequest Inefficiently
Invoke-WebRequest
sequentially in loops for multiple requests. Use parallelism with Start-Job
, ForEach-Object -Parallel
(in PowerShell 7+), or a module like PSParallel
for better performance.Not Using Appropriate Cmdlets for File Operations
Get-Content
, Set-Content
, Get-ChildItem
, etc., for file operations instead of .NET methods directly. The cmdlets are more idiomatic in PowerShell and often provide additional functionality like handling different encodings, working with the pipeline, and supporting PowerShell paths.Not Using Appropriate Comparison Operators
-eq
, -ne
, -gt
, -lt
, etc.) instead of C-style operators (==
, !=
, >
, <
, etc.). The PowerShell operators work consistently across all PowerShell versions and have special behavior for collections and wildcards.Not Using Appropriate String Comparison
-ieq
, -ine
, etc., for case-insensitive comparisons, and -ceq
, -cne
, etc., for case-sensitive comparisons.