powershell-master

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

PowerShell Master

PowerShell 精通指南

🚨 CRITICAL GUIDELINES

🚨 重要指南

Windows File Path Requirements

Windows 文件路径要求

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
强制要求:在Windows系统中操作文件路径时必须使用反斜杠(
\
在Windows系统中使用编辑或写入工具时,文件路径必须使用反斜杠(
\
),不能使用正斜杠(
/
)。
示例:
  • ❌ 错误:
    D:/repos/project/file.tsx
  • ✅ 正确:
    D:\repos\project\file.tsx
此要求适用于:
  • 编辑工具的file_path参数
  • 写入工具的file_path参数
  • Windows系统上的所有文件操作

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.

除非用户明确要求,否则绝不创建新的文档文件。
  • 优先级:优先更新现有README.md文件,而非创建新文档
  • 仓库整洁性:保持仓库根目录整洁 - 除非用户要求,否则仅保留README.md
  • 风格:文档应简洁、直接、专业 - 避免AI生成的冗余语气
  • 用户偏好:仅当用户明确要求文档时,才创建额外的.md文件

跨所有平台的完整PowerShell专业能力,涵盖脚本编写、自动化、CI/CD和云管理。

🎯 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相关的任务中主动启用:
  • PowerShell脚本 - 创建、审核、优化任何.ps1文件
  • Cmdlet与模块 - 查找、安装、使用任何PowerShell模块
  • 跨平台支持 - Windows、Linux、macOS系统下的PowerShell任务
  • CI/CD集成 - GitHub Actions、Azure DevOps、Bitbucket流水线
  • 云自动化 - Azure(Az)、AWS、Microsoft 365(Microsoft.Graph)
  • 模块管理 - PSGallery搜索、安装、更新
  • 脚本调试 - 故障排查、性能优化、安全检查
  • 最佳实践 - 代码质量、标准规范、生产级脚本

📋 PowerShell Overview

📋 PowerShell 概述

PowerShell Versions & Platforms

PowerShell 版本与平台

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

PowerShell 7+(推荐)
  • 跨平台:Windows、Linux、macOS
  • 开源、持续开发
  • 性能优于PowerShell 5.1
  • 默认使用UTF-8编码
  • 支持并行执行
  • 支持三元运算符、空合并运算符
Windows PowerShell 5.1(遗留版本)
  • 仅支持Windows系统
  • 随Windows系统预装
  • 默认使用UTF-16LE编码
  • 部分Windows专属模块依赖此版本
安装路径:
  • Windows:
    C:\Program Files\PowerShell\7\
    (PS7)或
    C:\Windows\System32\WindowsPowerShell\v1.0\
    (5.1)
  • Linux:
    /opt/microsoft/powershell/7/
    /usr/bin/pwsh
  • macOS:
    /usr/local/microsoft/powershell/7/
    /usr/local/bin/pwsh

🔧 Cross-Platform Best Practices

🔧 跨平台最佳实践

1. Path Handling

1. 路径处理

DO:
powershell
undefined
推荐做法:
powershell
undefined

Use Join-Path for cross-platform paths

Use Join-Path for cross-platform paths

$configPath = Join-Path -Path $PSScriptRoot -ChildPath "config.json"
$configPath = Join-Path -Path $PSScriptRoot -ChildPath "config.json"

Use [System.IO.Path] for path manipulation

Use [System.IO.Path] for path manipulation

$fullPath = [System.IO.Path]::Combine($home, "documents", "file.txt")
$fullPath = [System.IO.Path]::Combine($home, "documents", "file.txt")

Forward slashes work on all platforms in PowerShell 7+

Forward slashes work on all platforms in PowerShell 7+

$path = "$PSScriptRoot/subfolder/file.txt"

**DON'T:**
```powershell
$path = "$PSScriptRoot/subfolder/file.txt"

**不推荐做法:**
```powershell

Hardcoded backslashes (Windows-only)

Hardcoded backslashes (Windows-only)

$path = "C:\Users\Name\file.txt"
$path = "C:\Users\Name\file.txt"

Assume case-insensitive file systems

Assume case-insensitive file systems

Get-ChildItem "MyFile.txt" # Works on Windows, fails on Linux/macOS if casing is wrong
undefined
Get-ChildItem "MyFile.txt" # Works on Windows, fails on Linux/macOS if casing is wrong
undefined

2. Platform Detection

2. 平台检测

powershell
undefined
powershell
undefined

Use automatic variables

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 ':' }
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

Check PowerShell version

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

3. Avoid Aliases in Scripts

3. 脚本中避免使用别名

powershell
undefined
powershell
undefined

DON'T use aliases (they may differ across platforms)

DON'T use aliases (they may differ across platforms)

ls | ? {$.Length -gt 1MB} | % {$.Name}
ls | ? {$.Length -gt 1MB} | % {$.Name}

DO use full cmdlet names

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.
Get-ChildItem | Where-Object {$.Length -gt 1MB} | ForEach-Object {$.Name}

**原因:** 在Linux/macOS系统中,别名可能会调用原生命令而非PowerShell cmdlet,导致意外结果。

4. Text Encoding

4. 文本编码

powershell
undefined
powershell
undefined

PowerShell 7+ uses UTF-8 by default

PowerShell 7+ uses UTF-8 by default

"Hello" | Out-File -FilePath output.txt
"Hello" | Out-File -FilePath output.txt

For PowerShell 5.1 compatibility, specify encoding

For PowerShell 5.1 compatibility, specify encoding

"Hello" | Out-File -FilePath output.txt -Encoding UTF8
"Hello" | Out-File -FilePath output.txt -Encoding UTF8

Best practice: Always specify encoding for cross-platform scripts

Best practice: Always specify encoding for cross-platform scripts

$content | Set-Content -Path $file -Encoding UTF8NoBOM
undefined
$content | Set-Content -Path $file -Encoding UTF8NoBOM
undefined

5. Environment Variables (Cross-Platform)

5. 环境变量(跨平台)

powershell
undefined
powershell
undefined

BEST PRACTICE: Use .NET Environment class for cross-platform compatibility

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
[Environment]::UserName # Works on all platforms [Environment]::MachineName # Works on all platforms [IO.Path]::GetTempPath() # Works on all platforms

AVOID: These are platform-specific

AVOID: These are platform-specific

$env:USERNAME # Windows only $env:USER # Linux/macOS only
$env:USERNAME # Windows only $env:USER # Linux/macOS only

Environment variable names are CASE-SENSITIVE on Linux/macOS

Environment variable names are CASE-SENSITIVE on Linux/macOS

$env:PATH # Correct on Linux/macOS $env:Path # May not work on Linux/macOS
undefined
$env:PATH # Correct on Linux/macOS $env:Path # May not work on Linux/macOS
undefined

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

6. Shell检测(Windows:PowerShell vs Git Bash)

CRITICAL: On Windows, distinguish between PowerShell and Git Bash/MSYS2 environments:
powershell
undefined
关键提示: 在Windows系统中,需区分PowerShell和Git Bash/MSYS2环境:
powershell
undefined

PowerShell detection (most reliable)

PowerShell detection (most reliable)

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

Platform-specific automatic variables (PowerShell 7+)

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
if ($IsWindows) { # Windows-specific code } elseif ($IsLinux) { # Linux-specific code } elseif ($IsMacOS) { # macOS-specific code }

**Git Bash/MSYS2检测:**
```bash

Bash detection - check MSYSTEM environment variable

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.
if [ -n "$MSYSTEM" ]; then echo "Running in Git Bash/MSYS2: $MSYSTEM" # MSYSTEM values: MINGW64, MINGW32, MSYS fi

**各Shell适用场景:**
- **PowerShell:** Windows自动化、Azure/M365管理、PSGallery模块、对象流水线
- **Git Bash:** Git操作、Unix工具(sed/awk/grep)、POSIX脚本、文本处理

**路径处理差异:**
- **PowerShell:** `C:\Users\John` 或 `C:/Users/John`(在PS 7+中均有效)
- **Git Bash:** `/c/Users/John`(Unix风格,调用Windows工具时自动转换)

如需全面的跨Shell指导,请查看`powershell-shell-detection`技能。

7. Line Endings

7. 行尾格式

powershell
undefined
powershell
undefined

PowerShell handles line endings automatically

PowerShell handles line endings automatically

But be explicit for git or cross-platform tools

But be explicit for git or cross-platform tools

git config core.autocrlf input # Linux/macOS git config core.autocrlf true # Windows

---
git config core.autocrlf input # Linux/macOS git config core.autocrlf true # Windows

---

📦 Module Management (PSResourceGet & PSGallery)

📦 模块管理(PSResourceGet & PSGallery)

PSResourceGet - Modern Package Manager (2025)

PSResourceGet - 现代包管理器(2025)

PSResourceGet is 2x faster than PowerShellGet and actively maintained:
powershell
undefined
PSResourceGet 比PowerShellGet快2倍,且持续维护:
powershell
undefined

PSResourceGet ships with PowerShell 7.4+ (or install manually)

PSResourceGet ships with PowerShell 7.4+ (or install manually)

Install-Module -Name Microsoft.PowerShell.PSResourceGet -Force
Install-Module -Name Microsoft.PowerShell.PSResourceGet -Force

Modern commands (PSResourceGet)

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

Compatibility: Your old Install-Module commands still work

They automatically call PSResourceGet internally

They automatically call PSResourceGet internally

Install-Module -Name Az -Scope CurrentUser # Works, uses PSResourceGet
undefined
Install-Module -Name Az -Scope CurrentUser # Works, uses PSResourceGet
undefined

Finding Modules

查找模块

powershell
undefined
powershell
undefined

PSResourceGet (Modern)

PSResourceGet (Modern)

Find-PSResource -Name "Azure" Find-PSResource -Tag "Security" Find-PSResource -Name Az | Select-Object Name, Version, PublishedDate
Find-PSResource -Name "Azure" Find-PSResource -Tag "Security" Find-PSResource -Name Az | Select-Object Name, Version, PublishedDate

Legacy PowerShellGet (still works)

Legacy PowerShellGet (still works)

Find-Module -Name "Azure" Find-Command -Name Get-AzVM
undefined
Find-Module -Name "Azure" Find-Command -Name Get-AzVM
undefined

Installing Modules

安装模块

powershell
undefined
powershell
undefined

RECOMMENDED: PSResourceGet (2x faster)

RECOMMENDED: PSResourceGet (2x faster)

Install-PSResource -Name Az -Scope CurrentUser -TrustRepository Install-PSResource -Name Microsoft.Graph -Version 2.32.0
Install-PSResource -Name Az -Scope CurrentUser -TrustRepository Install-PSResource -Name Microsoft.Graph -Version 2.32.0

Legacy: PowerShellGet (slower, but still works)

Legacy: PowerShellGet (slower, but still works)

Install-Module -Name Az -Scope CurrentUser -Force Install-Module -Name Pester -Scope AllUsers # Requires elevation
undefined
Install-Module -Name Az -Scope CurrentUser -Force Install-Module -Name Pester -Scope AllUsers # Requires elevation
undefined

Managing Installed Modules

管理已安装模块

powershell
undefined
powershell
undefined

List installed (PSResourceGet)

List installed (PSResourceGet)

Get-InstalledPSResource Get-InstalledPSResource -Name Az
Get-InstalledPSResource Get-InstalledPSResource -Name Az

Update modules (PSResourceGet)

Update modules (PSResourceGet)

Update-PSResource -Name Az Update-PSResource # Updates all
Update-PSResource -Name Az Update-PSResource # Updates all

Uninstall (PSResourceGet)

Uninstall (PSResourceGet)

Uninstall-PSResource -Name OldModule -AllVersions
Uninstall-PSResource -Name OldModule -AllVersions

Import module

Import module

Import-Module -Name Az.Accounts
undefined
Import-Module -Name Az.Accounts
undefined

Offline Installation

离线安装

powershell
undefined
powershell
undefined

Save module (works with both)

Save module (works with both)

Save-PSResource -Name Az -Path C:\OfflineModules
Save-PSResource -Name Az -Path C:\OfflineModules

Or: Save-Module -Name Az -Path C:\OfflineModules

Or: Save-Module -Name Az -Path C:\OfflineModules

Install from saved location

Install from saved location

Install-PSResource -Name Az -Path C:\OfflineModules

---
Install-PSResource -Name Az -Path C:\OfflineModules

---

🌟 Popular PowerShell Modules

🌟 热门PowerShell模块

Azure (Az Module 14.5.0)

Azure(Az Module 14.5.0)

Latest: Az 14.5.0 (October 2025) with zone redundancy and symbolic links
powershell
undefined
最新版本: Az 14.5.0(2025年10月),支持区域冗余和符号链接
powershell
undefined

Install Azure module 14.5.0

Install Azure module 14.5.0

Install-PSResource -Name Az -Scope CurrentUser
Install-PSResource -Name Az -Scope CurrentUser

Or: Install-Module -Name Az -Scope CurrentUser -Force

Or: Install-Module -Name Az -Scope CurrentUser -Force

Connect to Azure

Connect to Azure

Connect-AzAccount
Connect-AzAccount

Common operations

Common operations

Get-AzVM Get-AzResourceGroup New-AzResourceGroup -Name "MyRG" -Location "EastUS"
Get-AzVM Get-AzResourceGroup New-AzResourceGroup -Name "MyRG" -Location "EastUS"

NEW in Az 14.5: Zone redundancy for storage

NEW in Az 14.5: Zone redundancy for storage

New-AzStorageAccount -ResourceGroupName "MyRG" -Name "storage123" ` -Location "EastUS" -SkuName "Standard_LRS" -EnableZoneRedundancy
New-AzStorageAccount -ResourceGroupName "MyRG" -Name "storage123" ` -Location "EastUS" -SkuName "Standard_LRS" -EnableZoneRedundancy

NEW in Az 14.5: Symbolic links in NFS File Share

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
New-AzStorageFileSymbolicLink -Context $ctx -ShareName "nfsshare" ` -Path "symlink" -Target "/target/path"

**核心子模块:**
- `Az.Accounts` - 身份验证(2025年9月起强制要求MFA)
- `Az.Compute` - 虚拟机、规模集
- `Az.Storage` - 存储账户(支持区域冗余)
- `Az.Network` - 虚拟网络、网络安全组
- `Az.KeyVault` - 密钥保管库操作
- `Az.Resources` - 资源组、部署

Microsoft Graph (Microsoft.Graph 2.32.0)

Microsoft Graph(Microsoft.Graph 2.32.0)

CRITICAL: MSOnline and AzureAD modules retired (March-May 2025). Use Microsoft.Graph instead.
powershell
undefined
关键提示: MSOnline和AzureAD模块已退役(2025年3-5月)。请使用Microsoft.Graph替代。
powershell
undefined

Install Microsoft Graph 2.32.0 (October 2025)

Install Microsoft Graph 2.32.0 (October 2025)

Install-PSResource -Name Microsoft.Graph -Scope CurrentUser
Install-PSResource -Name Microsoft.Graph -Scope CurrentUser

Or: Install-Module -Name Microsoft.Graph -Scope CurrentUser

Or: Install-Module -Name Microsoft.Graph -Scope CurrentUser

Connect with required scopes

Connect with required scopes

Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All"
Connect-MgGraph -Scopes "User.Read.All", "Group.ReadWrite.All"

Common operations

Common operations

Get-MgUser Get-MgGroup New-MgUser -DisplayName "John Doe" -UserPrincipalName "john@domain.com" -MailNickname "john" Get-MgTeam
Get-MgUser Get-MgGroup New-MgUser -DisplayName "John Doe" -UserPrincipalName "john@domain.com" -MailNickname "john" Get-MgTeam

Migration from AzureAD/MSOnline

Migration from AzureAD/MSOnline

OLD: Connect-AzureAD / Connect-MsolService

OLD: Connect-AzureAD / Connect-MsolService

NEW: Connect-MgGraph

NEW: Connect-MgGraph

OLD: Get-AzureADUser / Get-MsolUser

OLD: Get-AzureADUser / Get-MsolUser

NEW: Get-MgUser

NEW: Get-MgUser

undefined
undefined

PnP PowerShell (SharePoint/Teams)

PnP PowerShell(SharePoint/Teams)

powershell
undefined
powershell
undefined

Install PnP PowerShell

Install PnP PowerShell

Install-Module -Name PnP.PowerShell -Scope CurrentUser
Install-Module -Name PnP.PowerShell -Scope CurrentUser

Connect to SharePoint Online

Connect to SharePoint Online

Connect-PnPOnline -Url "https://tenant.sharepoint.com/sites/site" -Interactive
Connect-PnPOnline -Url "https://tenant.sharepoint.com/sites/site" -Interactive

Common operations

Common operations

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

AWS Tools for PowerShell

AWS Tools for PowerShell

powershell
undefined
powershell
undefined

Install AWS Tools

Install AWS Tools

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

Configure credentials

Configure credentials

Set-AWSCredential -AccessKey $accessKey -SecretKey $secretKey -StoreAs default
Set-AWSCredential -AccessKey $accessKey -SecretKey $secretKey -StoreAs default

Common operations

Common operations

Get-EC2Instance Get-S3Bucket New-S3Bucket -BucketName "my-bucket"
undefined
Get-EC2Instance Get-S3Bucket New-S3Bucket -BucketName "my-bucket"
undefined

Other Popular Modules

其他热门模块

powershell
undefined
powershell
undefined

Pester (Testing framework)

Pester (Testing framework)

Install-Module -Name Pester -Force
Install-Module -Name Pester -Force

PSScriptAnalyzer (Code analysis)

PSScriptAnalyzer (Code analysis)

Install-Module -Name PSScriptAnalyzer
Install-Module -Name PSScriptAnalyzer

ImportExcel (Excel manipulation without Excel)

ImportExcel (Excel manipulation without Excel)

Install-Module -Name ImportExcel
Install-Module -Name ImportExcel

PowerShellGet 3.x (Modern package management)

PowerShellGet 3.x (Modern package management)

Install-Module -Name Microsoft.PowerShell.PSResourceGet

---
Install-Module -Name Microsoft.PowerShell.PSResourceGet

---

🚀 CI/CD Integration

🚀 CI/CD 集成

GitHub Actions

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
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
多平台矩阵:
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

Azure DevOps 流水线

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'
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'
跨平台流水线:
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

Bitbucket 流水线

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

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

💻 PowerShell 语法与Cmdlet

Cmdlet Structure

Cmdlet 结构

powershell
undefined
powershell
undefined

Verb-Noun pattern

Verb-Noun pattern

Get-ChildItem Set-Location New-Item Remove-Item
Get-ChildItem Set-Location New-Item Remove-Item

Common parameters (available on all cmdlets)

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
undefined
Get-Process -Verbose Set-Content -Path file.txt -WhatIf Remove-Item -Path folder -Confirm Invoke-RestMethod -Uri $url -ErrorAction Stop
undefined

Variables & Data Types

变量与数据类型

powershell
undefined
powershell
undefined

Variables (loosely typed)

Variables (loosely typed)

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

Strongly typed

Strongly typed

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

Special variables

Special variables

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

Operators

运算符

powershell
undefined
powershell
undefined

Comparison operators

Comparison operators

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

Logical operators

Logical operators

-and -or -not
-and -or -not

PowerShell 7+ ternary operator

PowerShell 7+ ternary operator

$result = $condition ? "true" : "false"
$result = $condition ? "true" : "false"

Null-coalescing (PS 7+)

Null-coalescing (PS 7+)

$value = $null ?? "default"
undefined
$value = $null ?? "default"
undefined

Control Flow

控制流

powershell
undefined
powershell
undefined

If-ElseIf-Else

If-ElseIf-Else

if ($condition) { # Code } elseif ($otherCondition) { # Code } else { # Code }
if ($condition) { # Code } elseif ($otherCondition) { # Code } else { # Code }

Switch

Switch

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

Loops

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)
undefined
foreach ($item in $collection) { # Process item }
for ($i = 0; $i -lt 10; $i++) { # Loop code }
while ($condition) { # Loop code }
do { # Loop code } while ($condition)
undefined

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
    }
}
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
undefined
powershell
undefined

Pipeline basics

Pipeline basics

Get-Process | Where-Object {$_.CPU -gt 100} | Select-Object Name, CPU
Get-Process | Where-Object {$_.CPU -gt 100} | Select-Object Name, CPU

Simplified syntax (PS 3.0+)

Simplified syntax (PS 3.0+)

Get-Process | Where CPU -gt 100 | Select Name, CPU
Get-Process | Where CPU -gt 100 | Select Name, CPU

ForEach-Object

ForEach-Object

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

Simplified (PS 4.0+)

Simplified (PS 4.0+)

Get-ChildItem | % Name
Get-ChildItem | % Name

Group, Sort, Measure

Group, Sort, Measure

Get-Process | Group-Object ProcessName Get-Service | Sort-Object Status Get-ChildItem | Measure-Object -Property Length -Sum
undefined
Get-Process | Group-Object ProcessName Get-Service | Sort-Object Status Get-ChildItem | Measure-Object -Property Length -Sum
undefined

Error Handling

错误处理

powershell
undefined
powershell
undefined

Try-Catch-Finally

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 }
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

Error action preference

$ErrorActionPreference = "Stop" # Treat all errors as terminating $ErrorActionPreference = "Continue" # Default $ErrorActionPreference = "SilentlyContinue" # Suppress errors

---
$ErrorActionPreference = "Stop" # Treat all errors as terminating $ErrorActionPreference = "Continue" # Default $ErrorActionPreference = "SilentlyContinue" # Suppress errors

---

🔒 Security Best Practices (2025 Standards)

🔒 安全最佳实践(2025标准)

Modern Security Framework (JEA + WDAC + Logging)

现代安全框架(JEA + WDAC + 日志记录)

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
2025年安全要求:
  1. JEA - 最小权限管理(Just Enough Administration),基于角色的访问控制
  2. WDAC - Windows Defender应用控制,用于脚本审批
  3. 受限语言模式 - 针对非管理员用户
  4. 脚本块日志 - 用于审计追踪

Just Enough Administration (JEA)

最小权限管理(JEA)

Required for production environments in 2025:
powershell
undefined
2025年生产环境强制要求:
powershell
undefined

Create JEA session configuration file

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
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 JEA endpoint

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

Connect with limited privileges

Connect with limited privileges

Enter-PSSession -ComputerName Server01 -ConfigurationName HelpDesk
undefined
Enter-PSSession -ComputerName Server01 -ConfigurationName HelpDesk
undefined

Windows Defender Application Control (WDAC)

Windows Defender应用控制(WDAC)

Replaces AppLocker for PowerShell script control:
powershell
undefined
替代AppLocker用于PowerShell脚本控制:
powershell
undefined

Create WDAC policy for approved scripts

Create WDAC policy for approved scripts

New-CIPolicy -FilePath "C:\WDAC\PowerShellPolicy.xml"
    -ScanPath "C:\ApprovedScripts"
-Level FilePublisher ` -Fallback Hash
New-CIPolicy -FilePath "C:\WDAC\PowerShellPolicy.xml"
    -ScanPath "C:\ApprovedScripts"
-Level FilePublisher ` -Fallback Hash

Convert to binary

Convert to binary

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

Deploy via Group Policy or MDM

Deploy via Group Policy or MDM

undefined
undefined

Constrained Language Mode

受限语言模式

Recommended for all non-admin users:
powershell
undefined
推荐所有非管理员用户使用:
powershell
undefined

Check current language mode

Check current language mode

$ExecutionContext.SessionState.LanguageMode
$ExecutionContext.SessionState.LanguageMode

Output: FullLanguage (admin) or ConstrainedLanguage (standard user)

Output: FullLanguage (admin) or ConstrainedLanguage (standard user)

Enable system-wide via environment variable

Enable system-wide via environment variable

[Environment]::SetEnvironmentVariable( "__PSLockdownPolicy", "4", [System.EnvironmentVariableTarget]::Machine )
undefined
[Environment]::SetEnvironmentVariable( "__PSLockdownPolicy", "4", [System.EnvironmentVariableTarget]::Machine )
undefined

Script Block Logging

脚本块日志

Enable for security auditing:
powershell
undefined
启用用于安全审计:
powershell
undefined

Enable via Group Policy or Registry

Enable via Group Policy or Registry

HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging

HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging

EnableScriptBlockLogging = 1

EnableScriptBlockLogging = 1

EnableScriptBlockInvocationLogging = 1

EnableScriptBlockInvocationLogging = 1

Check logs

Check logs

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

Execution Policy

执行策略

powershell
undefined
powershell
undefined

Check current execution policy

Check current execution policy

Get-ExecutionPolicy
Get-ExecutionPolicy

Set for current user (no admin needed)

Set for current user (no admin needed)

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Bypass for single session (use sparingly)

Bypass for single session (use sparingly)

pwsh -ExecutionPolicy Bypass -File script.ps1
undefined
pwsh -ExecutionPolicy Bypass -File script.ps1
undefined

Credential Management

凭据管理

powershell
undefined
powershell
undefined

NEVER hardcode credentials

NEVER hardcode credentials

BAD: $password = "MyP@ssw0rd"

BAD: $password = "MyP@ssw0rd"

Use SecretManagement module (modern approach)

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

Legacy: Get-Credential for interactive

$cred = Get-Credential
$cred = Get-Credential

Azure Key Vault for production

Azure Key Vault for production

$vaultName = "MyKeyVault" $secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name "DatabasePassword" $secret.SecretValue
undefined
$vaultName = "MyKeyVault" $secret = Get-AzKeyVaultSecret -VaultName $vaultName -Name "DatabasePassword" $secret.SecretValue
undefined

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
    )
}
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
undefined
powershell
undefined

Get code signing certificate

Get code signing certificate

$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert
$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert

Sign script

Sign script

Set-AuthenticodeSignature -FilePath script.ps1 -Certificate $cert

---
Set-AuthenticodeSignature -FilePath script.ps1 -Certificate $cert

---

⚡ Performance Optimization

⚡ 性能优化

PowerShell 7+ Features

PowerShell 7+ 特性

powershell
undefined
powershell
undefined

Parallel ForEach (PS 7+)

Parallel ForEach (PS 7+)

1..10 | ForEach-Object -Parallel { Start-Sleep -Seconds 1 "Processed $_" } -ThrottleLimit 5
1..10 | ForEach-Object -Parallel { Start-Sleep -Seconds 1 "Processed $_" } -ThrottleLimit 5

Ternary operator

Ternary operator

$result = $value ? "true" : "false"
$result = $value ? "true" : "false"

Null-coalescing

Null-coalescing

$name = $userName ?? "default"
$name = $userName ?? "default"

Null-conditional member access

Null-conditional member access

$length = $string?.Length
undefined
$length = $string?.Length
undefined

Efficient Filtering

高效过滤

powershell
undefined
powershell
undefined

Use .NET methods for performance

Use .NET methods for performance

Instead of: Get-Content large.txt | Where-Object {$_ -match "pattern"}

Instead of: Get-Content large.txt | Where-Object {$_ -match "pattern"}

[System.IO.File]::ReadLines("large.txt") | Where-Object {$_ -match "pattern"}
[System.IO.File]::ReadLines("large.txt") | Where-Object {$_ -match "pattern"}

Use -Filter parameter when available

Use -Filter parameter when available

Get-ChildItem -Path C:\ -Filter *.log -Recurse
Get-ChildItem -Path C:\ -Filter *.log -Recurse

Instead of: Get-ChildItem -Path C:\ -Recurse | Where-Object {$_.Extension -eq ".log"}

Instead of: Get-ChildItem -Path C:\ -Recurse | Where-Object {$_.Extension -eq ".log"}

undefined
undefined

ArrayList vs Array

ArrayList vs Array

powershell
undefined
powershell
undefined

Arrays are immutable - slow for additions

Arrays are immutable - slow for additions

$array = @() 1..1000 | ForEach-Object { $array += $_ } # SLOW
$array = @() 1..1000 | ForEach-Object { $array += $_ } # SLOW

Use ArrayList for dynamic collections

Use ArrayList for dynamic collections

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

Or use generic List

Or use generic List

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

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

---

🧪 Testing with Pester

🧪 使用Pester进行测试

powershell
undefined
powershell
undefined

Install Pester

Install Pester

Install-Module -Name Pester -Force
Install-Module -Name Pester -Force

Basic test structure

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
    }
}
}
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

Run tests

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

Code coverage

Code coverage

Invoke-Pester -Path ./tests -CodeCoverage ./src/*.ps1

---
Invoke-Pester -Path ./tests -CodeCoverage ./src/*.ps1

---

📝 Script Requirements & Versioning

📝 脚本要求与版本控制

powershell
undefined
powershell
undefined

Require specific PowerShell version

Require specific PowerShell version

#Requires -Version 7.0
#Requires -Version 7.0

Require modules

Require modules

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

Require admin/elevated privileges (Windows)

Require admin/elevated privileges (Windows)

#Requires -RunAsAdministrator
#Requires -RunAsAdministrator

Combine multiple requirements

Combine multiple requirements

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

Use strict mode

Use strict mode

Set-StrictMode -Version Latest

---
Set-StrictMode -Version Latest

---

🎓 Common Cmdlets Reference

🎓 常用Cmdlet参考

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

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

🌐 REST API 与 Web 请求

powershell
undefined
powershell
undefined

GET request

GET request

$response = Invoke-RestMethod -Uri "https://api.example.com/data" -Method Get
$response = Invoke-RestMethod -Uri "https://api.example.com/data" -Method Get

POST with JSON body

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"
$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

With headers and authentication

$headers = @{ "Authorization" = "Bearer $token" "Accept" = "application/json" }
$response = Invoke-RestMethod -Uri $url -Headers $headers
$headers = @{ "Authorization" = "Bearer $token" "Accept" = "application/json" }
$response = Invoke-RestMethod -Uri $url -Headers $headers

Download file

Download file

Invoke-WebRequest -Uri $url -OutFile "file.zip"

---
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
)
powershell
<#
.SYNOPSIS
    简要描述

.DESCRIPTION
    详细描述

.PARAMETER Name
    参数说明

.EXAMPLE
    PS> .\script.ps1 -Name "John"
    示例用法

.NOTES
    作者:你的名字
    版本:1.0.0
    日期:2025-01-01
#>

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

Script-level error handling

Script-level error handling

$ErrorActionPreference = "Stop"
$ErrorActionPreference = "Stop"

Use strict mode

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 }

---
Set-StrictMode -Version Latest
try { # 主脚本逻辑 Write-Verbose "启动脚本"
# ... 脚本代码 ...

Write-Verbose "脚本执行成功"
} catch { Write-Error "脚本执行失败:$_" exit 1 } finally { # 清理操作 }

---

📚 Additional Resources

📚 额外资源

Official Documentation

官方文档

Module Discovery

模块发现

powershell
undefined
powershell
undefined

Find modules by keyword

Find modules by keyword

Find-Module -Tag "Azure" Find-Module -Tag "Security"
Find-Module -Tag "Azure" Find-Module -Tag "Security"

Explore commands in a module

Explore commands in a module

Get-Command -Module Az.Compute Get-Command -Verb Get -Noun VM
Get-Command -Module Az.Compute Get-Command -Verb Get -Noun VM

Get command help

Get command help

Get-Help Get-AzVM -Full Get-Help Get-AzVM -Examples Get-Help Get-AzVM -Online
undefined
Get-Help Get-AzVM -Full Get-Help Get-AzVM -Examples Get-Help Get-AzVM -Online
undefined

Update Help System

更新帮助系统

powershell
undefined
powershell
undefined

Update help files (requires internet)

Update help files (requires internet)

Update-Help -Force -ErrorAction SilentlyContinue
Update-Help -Force -ErrorAction SilentlyContinue

Update help for specific modules

Update help for specific modules

Update-Help -Module Az -Force

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

选择PowerShell 7+的场景:
  • 需要跨平台兼容性
  • 新项目或新脚本
  • 对性能有要求
  • 需要现代语言特性
选择Windows PowerShell 5.1的场景:
  • 依赖Windows专属模块(WSUS、GroupPolicy遗留版本)
  • 企业环境有严格的版本要求
  • 需要兼容遗留脚本
选择Azure CLI的场景:
  • 需要简单的单行命令
  • 偏好JSON输出
  • 需要与Bash脚本集成
选择PowerShell Az模块的场景:
  • 需要复杂的自动化
  • 需要对象操作
  • 具备PowerShell脚本专业能力
  • 需要可复用的脚本和模块

✅ 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

运行任何PowerShell脚本前,请确保:
  1. 平台检测 - 使用
    $IsWindows
    $IsLinux
    $IsMacOS
  2. 版本检查 - 如需特定版本,添加
    #Requires -Version 7.0
  3. 模块依赖 - 明确
    #Requires -Modules
    要求
  4. 错误处理 - 包含
    try/catch
  5. 输入验证 - 使用参数验证属性
  6. 无别名 - 脚本中使用完整cmdlet名称
  7. 路径处理 - 使用
    Join-Path
    [IO.Path]::Combine()
  8. 编码指定 - 跨平台脚本使用UTF-8编码
  9. 凭据安全 - 绝不硬编码凭据
  10. 详细日志 - 使用
    Write-Verbose
    用于调试

🚨 Common Pitfalls & Solutions

🚨 常见陷阱与解决方案

Pitfall: Out-GridView Search Broken in 7.5

陷阱:Out-GridView搜索在7.5版本中失效

powershell
undefined
powershell
undefined

Known Issue: Out-GridView search doesn't work in PowerShell 7.5 due to .NET 9 changes

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

Workaround: Use Where-Object or Select-Object for filtering

Get-Process | Where-Object CPU -gt 100 | Format-Table
Get-Process | Where-Object CPU -gt 100 | Format-Table

Or export to CSV and use external tools

Or export to CSV and use external tools

Get-Process | Export-Csv processes.csv -NoTypeInformation
undefined
Get-Process | Export-Csv processes.csv -NoTypeInformation
undefined

Pitfall: Case Sensitivity

陷阱:大小写敏感性

powershell
undefined
powershell
undefined

Linux/macOS are case-sensitive

Linux/macOS are case-sensitive

This fails on Linux if file is "File.txt"

This fails on Linux if file is "File.txt"

Get-Content "file.txt"
Get-Content "file.txt"

Solution: Use exact casing or Test-Path first

Solution: Use exact casing or Test-Path first

if (Test-Path "file.txt") { Get-Content "file.txt" }
undefined
if (Test-Path "file.txt") { Get-Content "file.txt" }
undefined

Pitfall: Execution Policy

陷阱:执行政策限制

powershell
undefined
powershell
undefined

Solution: Set for current user

Solution: Set for current user

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Or bypass for session

Or bypass for session

powershell.exe -ExecutionPolicy Bypass -File script.ps1
undefined
powershell.exe -ExecutionPolicy Bypass -File script.ps1
undefined

Pitfall: Module Import Failures

陷阱:模块导入失败

powershell
undefined
powershell
undefined

Solution: Check module availability and install

Solution: Check module availability and install

if (-not (Get-Module -ListAvailable -Name Az)) { Install-Module -Name Az -Force -Scope CurrentUser } Import-Module -Name Az
undefined
if (-not (Get-Module -ListAvailable -Name Az)) { Install-Module -Name Az -Force -Scope CurrentUser } Import-Module -Name Az
undefined

Pitfall: Array Concatenation Performance

陷阱:数组拼接性能问题

powershell
undefined
powershell
undefined

Bad: $array += $item (recreates array each time)

Bad: $array += $item (recreates array each time)

Good: Use ArrayList or List

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.
$list = [System.Collections.Generic.List[object]]::new() $list.Add($item)

---

注意:在实施解决方案前,请务必查阅最新的PowerShell文档和模块版本。PowerShell生态系统发展迅速,最佳实践会频繁更新。