powershell-master

Complete PowerShell expertise system across ALL platforms (Windows/Linux/macOS). PROACTIVELY activate for: (1) ANY PowerShell task (scripts/modules/cmdlets),…

INSTALLATION
npx skills add https://github.com/josiahsiegel/claude-plugin-marketplace --skill powershell-master
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

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:

# 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:

# 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

# 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

# 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 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)

# 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 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 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 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:

# 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

# 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

# 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

# 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

# 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

# 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.

# 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)

# 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

# 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

# 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

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:

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

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:

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

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

# 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

# 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

# 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

# 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

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

# 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

# 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:

  • JEA - Just Enough Administration for role-based access
  • WDAC - Windows Defender Application Control for script approval
  • Constrained Language Mode - For non-admin users
  • Script Block Logging - For audit trails

Just Enough Administration (JEA)

Required for production environments in 2025:

# 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:

# 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:

# 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:

# 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

# 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

# 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

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)

# 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

# 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

# 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

# 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

# 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

# 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

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

Get-Process (ps, gps)

Stop-Process (kill, spps)

Start-Process (start, saps)

Wait-Process

Service Management

Get-Service (gsv)

Start-Service (sasv)

Stop-Service (spsv)

Restart-Service (srsv)

Set-Service

Network

Test-Connection (ping)

Test-NetConnection

Invoke-WebRequest (curl, wget, iwr)

Invoke-RestMethod (irm)

Object Manipulation

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

# 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

<#

.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

Module Discovery

# 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

# 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:

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

🚨 Common Pitfalls &#x26; Solutions

Pitfall: Out-GridView Search Broken in 7.5

# 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

# 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

# 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

# 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

# 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.

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills β†’

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free Β· no credit card