| description | applyTo |
|---|---|
PowerShell development agent - robust, failsafe scripting with testing requirements |
**/*.ps1, **/*.psm1, **/*.psd1 |
- Always use proper error handling: Wrap operations in
try-catchblocks - Set strict error handling: Use
$ErrorActionPreference = 'Stop'at script start - Validate inputs: Check parameters, paths, and prerequisites before proceeding
- Test existence: Verify files, directories, and resources exist before accessing
- Use -ErrorAction explicitly: Never assume default error behavior
- Implement rollback mechanisms: For destructive operations, plan undo steps
- Add logging: Write informative messages for debugging and auditing
- Test every script: Execute the code in a test environment before considering it complete
- Verify edge cases: Test with empty inputs, missing files, permission issues
- Check return values: Ensure functions return expected types and values
- Test error paths: Intentionally trigger errors to verify handling works
- Document test results: Note what was tested and what passed/failed
- Ask when unclear: Never guess user intent, requirements, or environment details
- Confirm destructive operations: Always ask before deleting, modifying, or overwriting
- Clarify scope: Verify if script is for specific OS version, PowerShell version, or environment
- Request missing info: Ask about required permissions, expected input formats, output destinations
$ErrorActionPreference = 'Stop'
try {
# Validate prerequisites
if (-not (Test-Path $RequiredPath)) {
throw "Required path not found: $RequiredPath"
}
# Perform operations
$result = Invoke-Operation -ErrorAction Stop
# Verify results
if (-not $result) {
throw "Operation completed but returned no result"
}
Write-Host "Success: Operation completed" -ForegroundColor Green
return $result
}
catch {
Write-Error "Failed to complete operation: $_"
Write-Error $_.ScriptStackTrace
# Rollback if needed
exit 1
}[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string]$Path,
[Parameter(Mandatory=$false)]
[ValidateSet('Create', 'Update', 'Delete')]
[string]$Operation = 'Create',
[Parameter(Mandatory=$false)]
[ValidateRange(1, 100)]
[int]$RetryCount = 3
)function Invoke-SafeOperation {
<#
.SYNOPSIS
Brief description of function purpose
.DESCRIPTION
Detailed description including:
- What the function does
- Prerequisites/requirements
- Potential side effects
.PARAMETER ParameterName
Description of parameter
.EXAMPLE
Invoke-SafeOperation -Path "C:\Data" -Operation Create
.NOTES
Author: [Name/Generated]
Version: 1.0
Tested: [PowerShell versions, OS versions]
#>
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Mandatory=$true)]
[string]$Path
)
begin {
Write-Verbose "Starting operation with Path: $Path"
# Validation and setup
}
process {
try {
if ($PSCmdlet.ShouldProcess($Path, "Operation")) {
# Main logic
}
}
catch {
Write-Error "Failed: $_"
throw
}
}
end {
Write-Verbose "Operation completed"
# Cleanup
}
}- Understand the complete requirement
- Know the PowerShell version target (5.1, 7.x)
- Understand the OS environment (Windows, Linux, macOS)
- Identify required permissions/privileges
- Know the expected inputs and outputs
- Understand error handling expectations
- All operations have error handling
- All paths/resources are validated before use
- All parameters have appropriate validation attributes
- Destructive operations have confirmation prompts
- Code includes comprehensive comments
- Help documentation is complete
- Code has been tested in appropriate environment
- Edge cases have been considered and handled
# Always resolve and validate paths
$ResolvedPath = Resolve-Path $InputPath -ErrorAction SilentlyContinue
if (-not $ResolvedPath) {
throw "Invalid path: $InputPath"
}
# Prevent path traversal
$ResolvedPath = $ResolvedPath.Path
if ($ResolvedPath -notlike "$AllowedBasePath*") {
throw "Path outside allowed directory: $ResolvedPath"
}# Never hardcode credentials
# Use secure methods:
$Credential = Get-Credential
# Or use Windows Credential Manager
# Or use environment variables (for non-production only)
# Or use Azure Key Vault / Secret management
# Never log sensitive data
Write-Verbose "Connecting with username: $($Credential.UserName)"
# DON'T: Write-Verbose "Password: $($Credential.GetNetworkCredential().Password)"# Check permissions before operations
$Acl = Get-Acl $Path -ErrorAction Stop
$CurrentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
# Backup before destructive operations
if (Test-Path $TargetFile) {
$BackupPath = "$TargetFile.backup.$(Get-Date -Format 'yyyyMMddHHmmss')"
Copy-Item $TargetFile $BackupPath -ErrorAction Stop
Write-Host "Backup created: $BackupPath" -ForegroundColor Yellow
}
# Use -WhatIf and -Confirm for testing
[CmdletBinding(SupportsShouldProcess=$true)]- Happy path: Normal expected operation
- Invalid input: Wrong types, null values, empty strings
- Missing resources: Non-existent files, unavailable network paths
- Permission issues: Read-only files, protected directories
- Partial failures: Operations that partially complete
- Concurrent access: File locks, resource conflicts
Include in script comments:
<#
.TESTING
Tested on:
- PowerShell 7.4.0, Windows 11
- PowerShell 5.1, Windows Server 2019
Test scenarios executed:
- Valid file path with read/write permissions ✓
- Non-existent path (verified error handling) ✓
- Read-only file (verified error message) ✓
- Empty input (verified parameter validation) ✓
- Large file (>1GB) operation ✓
Known limitations:
- Requires elevated privileges for system directories
- Network paths require authentication
#>- Unclear requirements: "Should this script handle network paths or only local paths?"
- Ambiguous scope: "Should this run on PowerShell 5.1 or can I use PowerShell 7+ features?"
- Missing context: "What should happen if the file already exists?"
- Security concerns: "Should credentials be prompted interactively or retrieved from a secure store?"
- Performance considerations: "Are you processing small files or potentially large datasets?"
- Explain approach: Briefly describe the solution strategy
- Highlight considerations: Note important error handling, security measures
- Document testing: State what was tested and results
- Note limitations: Be clear about assumptions and constraints
- Provide usage examples: Show how to run the script safely
- Inform about testing progress: "Testing with invalid path..."
- Report test failures: "Found issue with permission handling, fixing..."
- Confirm successful tests: "All test scenarios passed ✓"
❌ DON'T:
- Use
Invoke-Expressionwith user input (code injection risk) - Suppress all errors with
-ErrorAction SilentlyContinueglobally - Assume paths exist without testing
- Hardcode paths, credentials, or environment-specific values
- Skip parameter validation
- Write scripts without try-catch blocks
- Deliver untested code
- Guess user requirements
✅ DO:
- Use parameterized commands and validated inputs
- Handle errors explicitly and appropriately
- Test paths with
Test-Pathbefore use - Use parameters, environment variables, or secure stores
- Use
[Parameter()]attributes with validation - Wrap risky operations in try-catch
- Test every code path before delivery
- Ask clarifying questions
- Always clarify target version
- Note features that require PowerShell 7+ (e.g., ternary operators, pipeline chain operators)
- Use version checks when needed:
if ($PSVersionTable.PSVersion.Major -lt 7) {
throw "This script requires PowerShell 7 or higher"
}# Path separators
$Separator = [System.IO.Path]::DirectorySeparatorChar
# Platform detection
if ($IsWindows -or $PSVersionTable.PSVersion.Major -eq 5) {
# Windows-specific code
}
elseif ($IsLinux) {
# Linux-specific code
}
elseif ($IsMacOS) {
# macOS-specific code
}Before marking any PowerShell code as complete:
- Tested: Code has been executed and verified
- Error handled: All operations wrapped in appropriate error handling
- Validated: All inputs checked before use
- Documented: Help text, comments, and examples included
- Secure: No hardcoded credentials, proper permission checks
- Idempotent: Can be run multiple times safely when appropriate
- Verbose: Adequate logging for troubleshooting
- Clear: No assumptions made without clarification
- Stop and ask - Don't proceed with uncertain requirements
- State assumptions - Make explicit what you're assuming
- Offer options - Present multiple approaches when applicable
- Test thoroughly - Better to over-test than under-test
- Document limitations - Be honest about what the code doesn't handle
Remember: Quality and safety over speed. Working code over clever code. Tested code over assumed code.