home / skills / josiahsiegel / claude-plugin-marketplace / powershell-master

powershell-master skill

/plugins/powershell-master/skills/powershell-master

npx playbooks add skill josiahsiegel/claude-plugin-marketplace --skill powershell-master

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
29.5 KB
---
name: powershell-master
description: "Complete PowerShell expertise system across ALL platforms (Windows/Linux/macOS). PROACTIVELY activate for: (1) ANY PowerShell task (scripts/modules/cmdlets), (2) CI/CD automation (GitHub Actions/Azure DevOps/Bitbucket), (3) Cross-platform scripting, (4) Module discovery and management (PSGallery), (5) Azure/AWS/Microsoft 365 automation, (6) Script debugging and optimization, (7) Best practices and security. Provides: PowerShell 7+ features, popular module expertise (Az, Microsoft.Graph, PnP, AWS Tools), PSGallery integration, platform-specific guidance, CI/CD pipeline patterns, cmdlet syntax mastery, and production-ready scripting patterns. Ensures professional-grade, cross-platform PowerShell automation following industry standards."
---

# PowerShell Master

## ๐Ÿšจ CRITICAL GUIDELINES

### Windows File Path Requirements

**MANDATORY: Always Use Backslashes on Windows for File Paths**

When using Edit or Write tools on Windows, you MUST use backslashes (`\`) in file paths, NOT forward slashes (`/`).

**Examples:**
- โŒ WRONG: `D:/repos/project/file.tsx`
- โœ… CORRECT: `D:\repos\project\file.tsx`

This applies to:
- Edit tool file_path parameter
- Write tool file_path parameter
- All file operations on Windows systems

### Documentation Guidelines

**NEVER create new documentation files unless explicitly requested by the user.**

- **Priority**: Update existing README.md files rather than creating new documentation
- **Repository cleanliness**: Keep repository root clean - only README.md unless user requests otherwise
- **Style**: Documentation should be concise, direct, and professional - avoid AI-generated tone
- **User preference**: Only create additional .md files when user specifically asks for documentation



---

Complete PowerShell expertise across all platforms for scripting, automation, CI/CD, and cloud management.

---

## ๐ŸŽฏ When to Activate

PROACTIVELY activate for ANY PowerShell-related task:

- โœ… **PowerShell Scripts** - Creating, reviewing, optimizing any .ps1 file
- โœ… **Cmdlets & Modules** - Finding, installing, using any PowerShell modules
- โœ… **Cross-Platform** - Windows, Linux, macOS PowerShell tasks
- โœ… **CI/CD Integration** - GitHub Actions, Azure DevOps, Bitbucket Pipelines
- โœ… **Cloud Automation** - Azure (Az), AWS, Microsoft 365 (Microsoft.Graph)
- โœ… **Module Management** - PSGallery search, installation, updates
- โœ… **Script Debugging** - Troubleshooting, performance, security
- โœ… **Best Practices** - Code quality, standards, production-ready scripts

---

## ๐Ÿ“‹ PowerShell Overview

### PowerShell Versions & Platforms

**PowerShell 7+ (Recommended)**
- Cross-platform: Windows, Linux, macOS
- Open source, actively developed
- Better performance than PowerShell 5.1
- UTF-8 by default
- Parallel execution support
- Ternary operators, null-coalescing

**Windows PowerShell 5.1 (Legacy)**
- Windows-only
- Ships with Windows
- UTF-16LE default encoding
- Required for some Windows-specific modules

**Installation Locations:**
- **Windows:** `C:\Program Files\PowerShell\7\` (PS7) or `C:\Windows\System32\WindowsPowerShell\v1.0\` (5.1)
- **Linux:** `/opt/microsoft/powershell/7/` or `/usr/bin/pwsh`
- **macOS:** `/usr/local/microsoft/powershell/7/` or `/usr/local/bin/pwsh`

---

## ๐Ÿ”ง Cross-Platform Best Practices

### 1. Path Handling

**DO:**
```powershell
# Use Join-Path for cross-platform paths
$configPath = Join-Path -Path $PSScriptRoot -ChildPath "config.json"

# Use [System.IO.Path] for path manipulation
$fullPath = [System.IO.Path]::Combine($home, "documents", "file.txt")

# Forward slashes work on all platforms in PowerShell 7+
$path = "$PSScriptRoot/subfolder/file.txt"
```

**DON'T:**
```powershell
# Hardcoded backslashes (Windows-only)
$path = "C:\Users\Name\file.txt"

# Assume case-insensitive file systems
Get-ChildItem "MyFile.txt"  # Works on Windows, fails on Linux/macOS if casing is wrong
```

### 2. Platform Detection

```powershell
# Use automatic variables
if ($IsWindows) {
    # Windows-specific code
    $env:Path -split ';'
}
elseif ($IsLinux) {
    # Linux-specific code
    $env:PATH -split ':'
}
elseif ($IsMacOS) {
    # macOS-specific code
    $env:PATH -split ':'
}

# Check PowerShell version
if ($PSVersionTable.PSVersion.Major -ge 7) {
    # PowerShell 7+ features
}
```

### 3. Avoid Aliases in Scripts

```powershell
# DON'T use aliases (they may differ across platforms)
ls | ? {$_.Length -gt 1MB} | % {$_.Name}

# DO use full cmdlet names
Get-ChildItem | Where-Object {$_.Length -gt 1MB} | ForEach-Object {$_.Name}
```

**Why:** On Linux/macOS, aliases might invoke native commands instead of PowerShell cmdlets, causing unexpected results.

### 4. Text Encoding

```powershell
# PowerShell 7+ uses UTF-8 by default
"Hello" | Out-File -FilePath output.txt

# For PowerShell 5.1 compatibility, specify encoding
"Hello" | Out-File -FilePath output.txt -Encoding UTF8

# Best practice: Always specify encoding for cross-platform scripts
$content | Set-Content -Path $file -Encoding UTF8NoBOM
```

### 5. Environment Variables (Cross-Platform)

```powershell
# BEST PRACTICE: Use .NET Environment class for cross-platform compatibility
[Environment]::UserName      # Works on all platforms
[Environment]::MachineName   # Works on all platforms
[IO.Path]::GetTempPath()     # Works on all platforms

# AVOID: These are platform-specific
$env:USERNAME                # Windows only
$env:USER                    # Linux/macOS only

# Environment variable names are CASE-SENSITIVE on Linux/macOS
$env:PATH    # Correct on Linux/macOS
$env:Path    # May not work on Linux/macOS
```

### 6. Shell Detection (Windows: PowerShell vs Git Bash)

**CRITICAL:** On Windows, distinguish between PowerShell and Git Bash/MSYS2 environments:

```powershell
# PowerShell detection (most reliable)
if ($env:PSModulePath -and ($env:PSModulePath -split ';').Count -ge 3) {
    Write-Host "Running in PowerShell"
}

# Platform-specific automatic variables (PowerShell 7+)
if ($IsWindows) {
    # Windows-specific code
}
elseif ($IsLinux) {
    # Linux-specific code
}
elseif ($IsMacOS) {
    # macOS-specific code
}
```

**Git Bash/MSYS2 Detection:**
```bash
# Bash detection - check MSYSTEM environment variable
if [ -n "$MSYSTEM" ]; then
    echo "Running in Git Bash/MSYS2: $MSYSTEM"
    # MSYSTEM values: MINGW64, MINGW32, MSYS
fi
```

**When to Use Each Shell:**
- **PowerShell:** Windows automation, Azure/M365, PSGallery modules, object pipelines
- **Git Bash:** Git operations, Unix tools (sed/awk/grep), POSIX scripts, text processing

**Path Handling Differences:**
- **PowerShell:** `C:\Users\John` or `C:/Users/John` (both work in PS 7+)
- **Git Bash:** `/c/Users/John` (Unix-style, auto-converts to Windows when calling Windows tools)

See `powershell-shell-detection` skill for comprehensive cross-shell guidance.

### 7. Line Endings

```powershell
# PowerShell handles line endings automatically
# But be explicit for git or cross-platform tools
git config core.autocrlf input  # Linux/macOS
git config core.autocrlf true   # Windows
```

---

## ๐Ÿ“ฆ Module Management (PSResourceGet & PSGallery)

### PSResourceGet - Modern Package Manager (2025)

**PSResourceGet** is 2x faster than PowerShellGet and actively maintained:

```powershell
# PSResourceGet ships with PowerShell 7.4+ (or install manually)
Install-Module -Name Microsoft.PowerShell.PSResourceGet -Force

# Modern commands (PSResourceGet)
Install-PSResource -Name Az -Scope CurrentUser        # 2x faster
Find-PSResource -Name "*Azure*"                       # Faster search
Update-PSResource -Name Az                            # Batch updates
Get-InstalledPSResource                               # List installed
Uninstall-PSResource -Name OldModule                  # Clean uninstall

# Compatibility: Your old Install-Module commands still work
# They automatically call PSResourceGet internally
Install-Module -Name Az -Scope CurrentUser            # Works, uses PSResourceGet
```

### Finding Modules

```powershell
# PSResourceGet (Modern)
Find-PSResource -Name "*Azure*"
Find-PSResource -Tag "Security"
Find-PSResource -Name Az | Select-Object Name, Version, PublishedDate

# Legacy PowerShellGet (still works)
Find-Module -Name "*Azure*"
Find-Command -Name Get-AzVM
```

### Installing Modules

```powershell
# RECOMMENDED: PSResourceGet (2x faster)
Install-PSResource -Name Az -Scope CurrentUser -TrustRepository
Install-PSResource -Name Microsoft.Graph -Version 2.32.0

# Legacy: PowerShellGet (slower, but still works)
Install-Module -Name Az -Scope CurrentUser -Force
Install-Module -Name Pester -Scope AllUsers  # Requires elevation
```

### Managing Installed Modules

```powershell
# List installed (PSResourceGet)
Get-InstalledPSResource
Get-InstalledPSResource -Name Az

# Update modules (PSResourceGet)
Update-PSResource -Name Az
Update-PSResource                              # Updates all

# Uninstall (PSResourceGet)
Uninstall-PSResource -Name OldModule -AllVersions

# Import module
Import-Module -Name Az.Accounts
```

### Offline Installation

```powershell
# Save module (works with both)
Save-PSResource -Name Az -Path C:\OfflineModules
# Or: Save-Module -Name Az -Path C:\OfflineModules

# Install from saved location
Install-PSResource -Name Az -Path C:\OfflineModules
```

---

## ๐ŸŒŸ Popular PowerShell Modules

### Azure (Az Module 14.5.0)

**Latest:** Az 14.5.0 (October 2025) with zone redundancy and symbolic links

```powershell
# Install Azure module 14.5.0
Install-PSResource -Name Az -Scope CurrentUser
# Or: Install-Module -Name Az -Scope CurrentUser -Force

# Connect to Azure
Connect-AzAccount

# Common operations
Get-AzVM
Get-AzResourceGroup
New-AzResourceGroup -Name "MyRG" -Location "EastUS"

# NEW in Az 14.5: Zone redundancy for storage
New-AzStorageAccount -ResourceGroupName "MyRG" -Name "storage123" `
    -Location "EastUS" -SkuName "Standard_LRS" -EnableZoneRedundancy

# NEW in Az 14.5: Symbolic links in NFS File Share
New-AzStorageFileSymbolicLink -Context $ctx -ShareName "nfsshare" `
    -Path "symlink" -Target "/target/path"
```

**Key Submodules:**
- `Az.Accounts` - Authentication (MFA required Sep 2025+)
- `Az.Compute` - VMs, scale sets
- `Az.Storage` - Storage accounts (zone redundancy support)
- `Az.Network` - Virtual networks, NSGs
- `Az.KeyVault` - Key Vault operations
- `Az.Resources` - Resource groups, deployments

### Microsoft Graph (Microsoft.Graph 2.32.0)

**CRITICAL:** MSOnline and AzureAD modules retired (March-May 2025). Use Microsoft.Graph instead.

```powershell
# Install Microsoft Graph 2.32.0 (October 2025)
Install-PSResource -Name Microsoft.Graph -Scope CurrentUser
# Or: Install-Module -Name Microsoft.Graph -Scope CurrentUser

# Connect with required scopes
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All"

# Common operations
Get-MgUser
Get-MgGroup
New-MgUser -DisplayName "John Doe" -UserPrincipalName "[email protected]" -MailNickname "john"
Get-MgTeam

# Migration from AzureAD/MSOnline
# OLD: Connect-AzureAD / Connect-MsolService
# NEW: Connect-MgGraph
# OLD: Get-AzureADUser / Get-MsolUser
# NEW: Get-MgUser
```

### PnP PowerShell (SharePoint/Teams)

```powershell
# Install PnP PowerShell
Install-Module -Name PnP.PowerShell -Scope CurrentUser

# Connect to SharePoint Online
Connect-PnPOnline -Url "https://tenant.sharepoint.com/sites/site" -Interactive

# Common operations
Get-PnPList
Get-PnPFile -Url "/sites/site/Shared Documents/file.docx"
Add-PnPListItem -List "Tasks" -Values @{"Title"="New Task"}
```

### AWS Tools for PowerShell

```powershell
# Install AWS Tools
Install-Module -Name AWS.Tools.Installer -Force
Install-AWSToolsModule AWS.Tools.EC2,AWS.Tools.S3

# Configure credentials
Set-AWSCredential -AccessKey $accessKey -SecretKey $secretKey -StoreAs default

# Common operations
Get-EC2Instance
Get-S3Bucket
New-S3Bucket -BucketName "my-bucket"
```

### Other Popular Modules

```powershell
# Pester (Testing framework)
Install-Module -Name Pester -Force

# PSScriptAnalyzer (Code analysis)
Install-Module -Name PSScriptAnalyzer

# ImportExcel (Excel manipulation without Excel)
Install-Module -Name ImportExcel

# PowerShellGet 3.x (Modern package management)
Install-Module -Name Microsoft.PowerShell.PSResourceGet
```

---

## ๐Ÿš€ CI/CD Integration

### GitHub Actions

```yaml
name: PowerShell CI

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install PowerShell modules
        shell: pwsh
        run: |
          Install-Module -Name Pester -Force -Scope CurrentUser
          Install-Module -Name PSScriptAnalyzer -Force -Scope CurrentUser

      - name: Run Pester tests
        shell: pwsh
        run: |
          Invoke-Pester -Path ./tests -OutputFormat NUnitXml -OutputFile TestResults.xml

      - name: Run PSScriptAnalyzer
        shell: pwsh
        run: |
          Invoke-ScriptAnalyzer -Path . -Recurse -ReportSummary
```

**Multi-Platform Matrix:**
```yaml
jobs:
  test:
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@v4
      - name: Test on ${{ matrix.os }}
        shell: pwsh
        run: |
          ./test-script.ps1
```

### Azure DevOps Pipelines

```yaml
trigger:
  - main

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: PowerShell@2
  inputs:
    targetType: 'inline'
    script: |
      Install-Module -Name Pester -Force -Scope CurrentUser
      Invoke-Pester -Path ./tests -OutputFormat NUnitXml
  displayName: 'Run Pester Tests'

- task: PowerShell@2
  inputs:
    filePath: '$(System.DefaultWorkingDirectory)/build.ps1'
    arguments: '-Configuration Release'
  displayName: 'Run Build Script'

- task: PublishTestResults@2
  inputs:
    testResultsFormat: 'NUnit'
    testResultsFiles: '**/TestResults.xml'
```

**Cross-Platform Pipeline:**
```yaml
strategy:
  matrix:
    linux:
      imageName: 'ubuntu-latest'
    windows:
      imageName: 'windows-latest'
    mac:
      imageName: 'macos-latest'

pool:
  vmImage: $(imageName)

steps:
- pwsh: |
    Write-Host "Running on $($PSVersionTable.OS)"
    ./test-script.ps1
  displayName: 'Cross-platform test'
```

### Bitbucket Pipelines

```yaml
image: mcr.microsoft.com/powershell:latest

pipelines:
  default:
    - step:
        name: Test with PowerShell
        script:
          - pwsh -Command "Install-Module -Name Pester -Force"
          - pwsh -Command "Invoke-Pester -Path ./tests"

    - step:
        name: Deploy
        deployment: production
        script:
          - pwsh -File ./deploy.ps1
```

---

## ๐Ÿ’ป PowerShell Syntax & Cmdlets

### Cmdlet Structure

```powershell
# Verb-Noun pattern
Get-ChildItem
Set-Location
New-Item
Remove-Item

# Common parameters (available on all cmdlets)
Get-Process -Verbose
Set-Content -Path file.txt -WhatIf
Remove-Item -Path folder -Confirm
Invoke-RestMethod -Uri $url -ErrorAction Stop
```

### Variables & Data Types

```powershell
# Variables (loosely typed)
$string = "Hello World"
$number = 42
$array = @(1, 2, 3, 4, 5)
$hashtable = @{Name="John"; Age=30}

# Strongly typed
[string]$name = "John"
[int]$age = 30
[datetime]$date = Get-Date

# Special variables
$PSScriptRoot  # Directory containing the script
$PSCommandPath  # Full path to the script
$args  # Script arguments
$_  # Current pipeline object
```

### Operators

```powershell
# Comparison operators
-eq  # Equal
-ne  # Not equal
-gt  # Greater than
-lt  # Less than
-match  # Regex match
-like  # Wildcard match
-contains  # Array contains

# Logical operators
-and
-or
-not

# PowerShell 7+ ternary operator
$result = $condition ? "true" : "false"

# Null-coalescing (PS 7+)
$value = $null ?? "default"
```

### Control Flow

```powershell
# If-ElseIf-Else
if ($condition) {
    # Code
} elseif ($otherCondition) {
    # Code
} else {
    # Code
}

# Switch
switch ($value) {
    1 { "One" }
    2 { "Two" }
    {$_ -gt 10} { "Greater than 10" }
    default { "Other" }
}

# Loops
foreach ($item in $collection) {
    # Process item
}

for ($i = 0; $i -lt 10; $i++) {
    # Loop code
}

while ($condition) {
    # Loop code
}

do {
    # Loop code
} while ($condition)
```

### Functions

```powershell
function Get-Something {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$Name,

        [Parameter()]
        [int]$Count = 1,

        [Parameter(ValueFromPipeline=$true)]
        [string[]]$InputObject
    )

    begin {
        # Initialization
    }

    process {
        # Process each pipeline object
        foreach ($item in $InputObject) {
            # Work with $item
        }
    }

    end {
        # Cleanup
        return $result
    }
}
```

### Pipeline & Filtering

```powershell
# Pipeline basics
Get-Process | Where-Object {$_.CPU -gt 100} | Select-Object Name, CPU

# Simplified syntax (PS 3.0+)
Get-Process | Where CPU -gt 100 | Select Name, CPU

# ForEach-Object
Get-ChildItem | ForEach-Object {
    Write-Host $_.Name
}

# Simplified (PS 4.0+)
Get-ChildItem | % Name

# Group, Sort, Measure
Get-Process | Group-Object ProcessName
Get-Service | Sort-Object Status
Get-ChildItem | Measure-Object -Property Length -Sum
```

### Error Handling

```powershell
# Try-Catch-Finally
try {
    Get-Content -Path "nonexistent.txt" -ErrorAction Stop
}
catch [System.IO.FileNotFoundException] {
    Write-Error "File not found"
}
catch {
    Write-Error "An error occurred: $_"
}
finally {
    # Cleanup code
}

# Error action preference
$ErrorActionPreference = "Stop"  # Treat all errors as terminating
$ErrorActionPreference = "Continue"  # Default
$ErrorActionPreference = "SilentlyContinue"  # Suppress errors
```

---

## ๐Ÿ”’ Security Best Practices (2025 Standards)

### Modern Security Framework (JEA + WDAC + Logging)

**2025 Security Requirements:**
1. **JEA** - Just Enough Administration for role-based access
2. **WDAC** - Windows Defender Application Control for script approval
3. **Constrained Language Mode** - For non-admin users
4. **Script Block Logging** - For audit trails

### Just Enough Administration (JEA)

**Required for production environments in 2025:**

```powershell
# Create JEA session configuration file
New-PSSessionConfigurationFile -SessionType RestrictedRemoteServer `
    -Path "C:\JEA\HelpDesk.pssc" `
    -VisibleCmdlets @{
        Name = 'Restart-Service'
        Parameters = @{ Name = 'Name'; ValidateSet = 'Spooler', 'Wuauserv' }
    }, @{
        Name = 'Get-Service'
    } `
    -LanguageMode NoLanguage `
    -ExecutionPolicy RemoteSigned

# Register JEA endpoint
Register-PSSessionConfiguration -Name HelpDesk `
    -Path "C:\JEA\HelpDesk.pssc" `
    -Force

# Connect with limited privileges
Enter-PSSession -ComputerName Server01 -ConfigurationName HelpDesk
```

### Windows Defender Application Control (WDAC)

**Replaces AppLocker for PowerShell script control:**

```powershell
# Create WDAC policy for approved scripts
New-CIPolicy -FilePath "C:\WDAC\PowerShellPolicy.xml" `
    -ScanPath "C:\ApprovedScripts" `
    -Level FilePublisher `
    -Fallback Hash

# Convert to binary
ConvertFrom-CIPolicy -XmlFilePath "C:\WDAC\PowerShellPolicy.xml" `
    -BinaryFilePath "C:\Windows\System32\CodeIntegrity\SIPolicy.p7b"

# Deploy via Group Policy or MDM
```

### Constrained Language Mode

**Recommended for all non-admin users:**

```powershell
# Check current language mode
$ExecutionContext.SessionState.LanguageMode
# Output: FullLanguage (admin) or ConstrainedLanguage (standard user)

# Enable system-wide via environment variable
[Environment]::SetEnvironmentVariable(
    "__PSLockdownPolicy",
    "4",
    [System.EnvironmentVariableTarget]::Machine
)
```

### Script Block Logging

**Enable for security auditing:**

```powershell
# Enable via Group Policy or Registry
# HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
# EnableScriptBlockLogging = 1
# EnableScriptBlockInvocationLogging = 1

# Check logs
Get-WinEvent -LogName "Microsoft-Windows-PowerShell/Operational" |
    Where-Object Id -eq 4104 |  # Script Block Logging
    Select-Object TimeCreated, Message -First 10
```

### Execution Policy

```powershell
# Check current execution policy
Get-ExecutionPolicy

# Set for current user (no admin needed)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

# Bypass for single session (use sparingly)
pwsh -ExecutionPolicy Bypass -File script.ps1
```

### Credential Management

```powershell
# NEVER hardcode credentials
# BAD: $password = "MyP@ssw0rd"

# Use SecretManagement module (modern approach)
Install-PSResource -Name Microsoft.PowerShell.SecretManagement
Install-PSResource -Name SecretManagement.KeyVault

Register-SecretVault -Name AzureKeyVault -ModuleName SecretManagement.KeyVault
$secret = Get-Secret -Name "DatabasePassword" -Vault AzureKeyVault

# Legacy: Get-Credential for interactive
$cred = Get-Credential

# Azure Key Vault for production
$vaultName = "MyKeyVault"
$secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name "DatabasePassword"
$secret.SecretValue
```

### Input Validation

```powershell
function Do-Something {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [string]$Name,

        [Parameter()]
        [ValidateRange(1, 100)]
        [int]$Count,

        [Parameter()]
        [ValidateSet("Option1", "Option2", "Option3")]
        [string]$Option,

        [Parameter()]
        [ValidatePattern('^\d{3}-\d{3}-\d{4}$')]
        [string]$PhoneNumber
    )
}
```

### Code Signing (Production)

```powershell
# Get code signing certificate
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert

# Sign script
Set-AuthenticodeSignature -FilePath script.ps1 -Certificate $cert
```

---

## โšก Performance Optimization

### PowerShell 7+ Features

```powershell
# Parallel ForEach (PS 7+)
1..10 | ForEach-Object -Parallel {
    Start-Sleep -Seconds 1
    "Processed $_"
} -ThrottleLimit 5

# Ternary operator
$result = $value ? "true" : "false"

# Null-coalescing
$name = $userName ?? "default"

# Null-conditional member access
$length = $string?.Length
```

### Efficient Filtering

```powershell
# Use .NET methods for performance
# Instead of: Get-Content large.txt | Where-Object {$_ -match "pattern"}
[System.IO.File]::ReadLines("large.txt") | Where-Object {$_ -match "pattern"}

# Use -Filter parameter when available
Get-ChildItem -Path C:\ -Filter *.log -Recurse
# Instead of: Get-ChildItem -Path C:\ -Recurse | Where-Object {$_.Extension -eq ".log"}
```

### ArrayList vs Array

```powershell
# Arrays are immutable - slow for additions
$array = @()
1..1000 | ForEach-Object { $array += $_ }  # SLOW

# Use ArrayList for dynamic collections
$list = [System.Collections.ArrayList]::new()
1..1000 | ForEach-Object { [void]$list.Add($_) }  # FAST

# Or use generic List
$list = [System.Collections.Generic.List[int]]::new()
1..1000 | ForEach-Object { $list.Add($_) }
```

---

## ๐Ÿงช Testing with Pester

```powershell
# Install Pester
Install-Module -Name Pester -Force

# Basic test structure
Describe "Get-Something Tests" {
    Context "When input is valid" {
        It "Should return expected value" {
            $result = Get-Something -Name "Test"
            $result | Should -Be "Expected"
        }
    }

    Context "When input is invalid" {
        It "Should throw an error" {
            { Get-Something -Name $null } | Should -Throw
        }
    }
}

# Run tests
Invoke-Pester -Path ./tests
Invoke-Pester -Path ./tests -OutputFormat NUnitXml -OutputFile TestResults.xml

# Code coverage
Invoke-Pester -Path ./tests -CodeCoverage ./src/*.ps1
```

---

## ๐Ÿ“ Script Requirements & Versioning

```powershell
# Require specific PowerShell version
#Requires -Version 7.0

# Require modules
#Requires -Modules Az.Accounts, Az.Compute

# Require admin/elevated privileges (Windows)
#Requires -RunAsAdministrator

# Combine multiple requirements
#Requires -Version 7.0
#Requires -Modules @{ModuleName='Pester'; ModuleVersion='5.0.0'}

# Use strict mode
Set-StrictMode -Version Latest
```

---

## ๐ŸŽ“ Common Cmdlets Reference

### File System
```powershell
Get-ChildItem (gci, ls, dir)
Set-Location (cd, sl)
New-Item (ni)
Remove-Item (rm, del)
Copy-Item (cp, copy)
Move-Item (mv, move)
Rename-Item (rn, ren)
Get-Content (gc, cat, type)
Set-Content (sc)
Add-Content (ac)
```

### Process Management
```powershell
Get-Process (ps, gps)
Stop-Process (kill, spps)
Start-Process (start, saps)
Wait-Process
```

### Service Management
```powershell
Get-Service (gsv)
Start-Service (sasv)
Stop-Service (spsv)
Restart-Service (srsv)
Set-Service
```

### Network
```powershell
Test-Connection (ping)
Test-NetConnection
Invoke-WebRequest (curl, wget, iwr)
Invoke-RestMethod (irm)
```

### Object Manipulation
```powershell
Select-Object (select)
Where-Object (where, ?)
ForEach-Object (foreach, %)
Sort-Object (sort)
Group-Object (group)
Measure-Object (measure)
Compare-Object (compare, diff)
```

---

## ๐ŸŒ REST API & Web Requests

```powershell
# GET request
$response = Invoke-RestMethod -Uri "https://api.example.com/data" -Method Get

# POST with JSON body
$body = @{
    name = "John"
    age = 30
} | ConvertTo-Json

$response = Invoke-RestMethod -Uri "https://api.example.com/users" `
    -Method Post -Body $body -ContentType "application/json"

# With headers and authentication
$headers = @{
    "Authorization" = "Bearer $token"
    "Accept" = "application/json"
}

$response = Invoke-RestMethod -Uri $url -Headers $headers

# Download file
Invoke-WebRequest -Uri $url -OutFile "file.zip"
```

---

## ๐Ÿ—๏ธ Script Structure Best Practices

```powershell
<#
.SYNOPSIS
    Brief description

.DESCRIPTION
    Detailed description

.PARAMETER Name
    Parameter description

.EXAMPLE
    PS> .\script.ps1 -Name "John"
    Example usage

.NOTES
    Author: Your Name
    Version: 1.0.0
    Date: 2025-01-01
#>

[CmdletBinding()]
param(
    [Parameter(Mandatory=$true)]
    [string]$Name
)

# Script-level error handling
$ErrorActionPreference = "Stop"

# Use strict mode
Set-StrictMode -Version Latest

try {
    # Main script logic
    Write-Verbose "Starting script"

    # ... script code ...

    Write-Verbose "Script completed successfully"
}
catch {
    Write-Error "Script failed: $_"
    exit 1
}
finally {
    # Cleanup
}
```

---

## ๐Ÿ“š Additional Resources

### Official Documentation
- PowerShell Docs: https://learn.microsoft.com/powershell
- PowerShell Gallery: https://www.powershellgallery.com
- Az Module Docs: https://learn.microsoft.com/powershell/azure
- Microsoft Graph Docs: https://learn.microsoft.com/graph/powershell

### Module Discovery
```powershell
# Find modules by keyword
Find-Module -Tag "Azure"
Find-Module -Tag "Security"

# Explore commands in a module
Get-Command -Module Az.Compute
Get-Command -Verb Get -Noun *VM*

# Get command help
Get-Help Get-AzVM -Full
Get-Help Get-AzVM -Examples
Get-Help Get-AzVM -Online
```

### Update Help System
```powershell
# Update help files (requires internet)
Update-Help -Force -ErrorAction SilentlyContinue

# Update help for specific modules
Update-Help -Module Az -Force
```

---

## ๐ŸŽฏ Quick Decision Guide

**Use PowerShell 7+ when:**
- Cross-platform compatibility needed
- New projects or scripts
- Performance is important
- Modern language features desired

**Use Windows PowerShell 5.1 when:**
- Windows-specific modules required (WSUS, GroupPolicy legacy)
- Corporate environments with strict version requirements
- Legacy script compatibility needed

**Choose Azure CLI when:**
- Simple one-liners needed
- JSON output preferred
- Bash scripting integration

**Choose PowerShell Az module when:**
- Complex automation required
- Object manipulation needed
- PowerShell scripting expertise available
- Reusable scripts and modules needed

---

## โœ… Pre-Flight Checklist for Scripts

Before running any PowerShell script, ensure:

1. โœ… **Platform Detection** - Use `$IsWindows`, `$IsLinux`, `$IsMacOS`
2. โœ… **Version Check** - `#Requires -Version 7.0` if needed
3. โœ… **Module Requirements** - `#Requires -Modules` specified
4. โœ… **Error Handling** - `try/catch` blocks in place
5. โœ… **Input Validation** - Parameter validation attributes used
6. โœ… **No Aliases** - Full cmdlet names in scripts
7. โœ… **Path Handling** - Use `Join-Path` or `[IO.Path]::Combine()`
8. โœ… **Encoding Specified** - UTF-8 for cross-platform
9. โœ… **Credentials Secure** - Never hardcoded
10. โœ… **Verbose Logging** - `Write-Verbose` for debugging

---

## ๐Ÿšจ Common Pitfalls & Solutions

### Pitfall: Out-GridView Search Broken in 7.5
```powershell
# Known Issue: Out-GridView search doesn't work in PowerShell 7.5 due to .NET 9 changes
# Workaround: Use Where-Object or Select-Object for filtering
Get-Process | Where-Object CPU -gt 100 | Format-Table

# Or export to CSV and use external tools
Get-Process | Export-Csv processes.csv -NoTypeInformation
```

### Pitfall: Case Sensitivity
```powershell
# Linux/macOS are case-sensitive
# This fails on Linux if file is "File.txt"
Get-Content "file.txt"

# Solution: Use exact casing or Test-Path first
if (Test-Path "file.txt") {
    Get-Content "file.txt"
}
```

### Pitfall: Execution Policy
```powershell
# Solution: Set for current user
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

# Or bypass for session
powershell.exe -ExecutionPolicy Bypass -File script.ps1
```

### Pitfall: Module Import Failures
```powershell
# Solution: Check module availability and install
if (-not (Get-Module -ListAvailable -Name Az)) {
    Install-Module -Name Az -Force -Scope CurrentUser
}
Import-Module -Name Az
```

### Pitfall: Array Concatenation Performance
```powershell
# Bad: $array += $item (recreates array each time)

# Good: Use ArrayList or List
$list = [System.Collections.Generic.List[object]]::new()
$list.Add($item)
```

---

Remember: ALWAYS research latest PowerShell documentation and module versions before implementing solutions. The PowerShell ecosystem evolves rapidly, and best practices are updated frequently.