| name | powershell-advanced-patterns |
| description | Consolidated guidelines for advanced PowerShell scripting and testing, covering .NET type mocking via accelerators, scope isolation in modules, and robust admin privilege handling/NTFS file deletion. |
Advanced PowerShell Scripting & Testing Guidelines
Use this skill when developing, refactoring, or reviewing advanced PowerShell modules and test suites in this repository. It consolidates patterns for mocking, sandbox environment setup, scope/session isolation, and robust elevated administration actions.
1. Mocking & Sandbox Testing Patterns
A. Type Accelerator Redirection Pattern
Fully qualified .NET class names (e.g., [System.IO.File] or [Microsoft.Win32.Registry]) bypass custom type accelerator overrides because PowerShell resolves them directly via CLR type lookups.
Recommended Implementation:
- In the Script Under Test:
- In the Test Runner:
B. Fully Qualified Type Mocking via Class Reference Variables
When code under test calls fully qualified static methods directly, replacing all instances with a short name might be verbose.
Recommended Implementation:
- In the Script/Module Under Test:
Declare script-scoped class reference variables at the top of the file/module helper:
$script:WindowsIdentityClass = [System.Security.Principal.WindowsIdentity]
$script:RegistryClass = [Microsoft.Win32.Registry]
if ($env:IsTestRunner) {
$script:WindowsIdentityClass = [MockWindowsIdentity]
$script:RegistryClass = [MockRegistry]
}
- Throughout the Script:
Invoke static methods/properties through the reference variable:
$identity = $script:WindowsIdentityClass::GetCurrent()
$key = $script:RegistryClass::CurrentUser.OpenSubKey("Environment")
C. Path Normalization in Mocks
Asserting against command execution strings with file paths often fails when run in sandboxes due to temporary host-specific absolute paths.
2. Module Scope & Environment Isolation
A. Dot-Sourcing Scope & $WhatIfPreference Leakage
Dot-sourcing a script under test running with -DryRun or -WhatIf sets $WhatIfPreference = $true in the caller's session scope, persisting after execution and silencing subsequent disk writes in finally blocks.
B. Test Harness Module Scope Isolation
PowerShell modules run in an isolated Module Session State. They bypass script-scoped mock functions in custom test runners.
C. Path Resolution Pitfall ($PSScriptRoot vs LocalAppData)
In a module, $PSScriptRoot points to the module's installation directory, which is often read-only.
3. Elevated Administration & File Operations
A. Session-Aware Elevation Profile Resolution
When running elevated, environment variables like $env:USERNAME map to the Administrator account. Querying explorer.exe process owner can resolve the wrong user in multi-session environments.
B. Robust File Deletion Hierarchy (System-Locked & Reparse Points)
Execution aliases and system files implementing NTFS reparse points often fail standard deletion calls.
- Pattern: Implement a multi-stage fallback mechanism:
- Native API (if reparse point):
fsutil reparsepoint delete "$shortPath"
- .NET API:
[System.IO.File]::Delete($Path)
- ACL Remediation: Use
takeown.exe and icacls.exe to take ownership and grant FullControl (F) to current user, then retry.
- CMD Fallback: Use
cmd.exe /c del /f /q.
4. Diagnostic Robustness & Optional Component Tolerances
When auditing environments or checking package aliases, distinguish between mandatory dependencies (e.g., winget.exe) and optional or dev-only additions (e.g., wingetdev.exe).
- Rule 1: Optional File Tolerances: If a file is optional, do not flag the system check as
FAIL when the file does not exist. Instead, log its absence as [Info] or [Warn].
- Rule 2: Conditional Corrupted Validation: If the optional component does exist, execute full verification (e.g., check if it is a valid NTFS reparse point). If it exists but is corrupted, flag it as
FAIL and trigger repair.
Recommended Implementation Pattern:
foreach ($alias in $aliases) {
if (Test-Path $aliasPath) {
# Perform strict checks (e.g. check if it is a reparse point)
} else {
if ($alias -eq "optional.exe") {
Write-Log -Message "Alias [$alias] not present (optional)." -Level "Info"
} else {
$state = "FAIL"
Write-Log -Message "Alias [$alias] is missing!" -Level "Error"
}
}
}
5. Verification Checklist