--- 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 "john@domain.com" -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.