目录

基础

参考文档

重要的命令

核心运行逻辑:对象与管道

基础语法

数据结构与类型

基本数据类型

类型写法示例说明
字符串[string]$S = "Hello"文本
整数[int]$i = 1032 位整数
长整数[long]$i = 10000000000大数字
布尔[bool]$b = $true真/假
小数[double]$d = 3.14浮点数
日期[datetime]$dt = Get-Date时间对象
空值$null$x = $null无值
function Start-Service {
    param (
        [switch]$Force  # 调用时只需写 -Force,不用写 -Force $true
    )
    if ($Force) { Write-Host "强制执行" }
}

Start-Service -Force  # $Force 自动变为 $true

数组

# 定义
$arr = @()                 # 空数组
$arr = 1, 2, 3             # 快速定义
$arr = @("A", "B", "C")    # 显式定义

# 访问
$arr[0]        # 第一个元素
$arr[-1]       # 最后一个元素 (负数索引)
$arr.Count     # 长度

# 添加 (注意:这会创建新数组,大数据量时性能差)
$arr += 4

哈希表 (Hashtables)

# 定义
$hash = @{
    Name = "Admin"
    ID   = 101
    Active = $true
}
[hashtable]$props=@{}

# 访问
$hash.Name       # 点号访问
$hash["ID"]      # 索引访问

# 添加/修改
$hash["Location"] = "Beijing"

# 遍历
foreach ($key in $hash.Keys) {
    Write-Host "$key : $($hash[$key])"
}

# 高级用法:参数 splatting, 哈希表常用于将一堆参数“展开”传递给命令,使代码更整洁。
$params = @{
    Path = "C:\Log"
    Filter = "*.txt"
    Recurse = $true
}
Get-ChildItem @params  # 注意这里是 @ 而不是 $

# 泛型哈希
System.Collections.Generic.Dictionary[K,V]

集合类型

# 定义
[ArrayList]$list = [ArrayList]::new()
# 或者
$list = [System.Collections.ArrayList]@()

# 添加元素 (⚠️ 必须用 $null = 接收返回值,否则屏幕会打印数字)
$null = $list.Add("Apple")
$null = $list.Add(123)
$null = $list.Add(@("Nested", "Array"))

# 添加多个
$null = $list.AddRange(@("A", "B", "C"))

# 访问
$list[0]          # "Apple"
$list.Count       # 6

# 删除
$null = $list.Remove("Apple")
$null = $list.RemoveAt(0)
# 定义 (指定只能存字符串)
[System.Collections.Generic.List[string]]$list = [System.Collections.Generic.List[string]]::new()

# 添加 (不需要 $null =,因为 .Add() 返回 void)
$list.Add("Apple")
$list.Add("Banana")
# $list.Add(123)  # ❌ 报错!类型不匹配

# 访问
$list[0]
$list.Count

# 查找
$list.Contains("Apple")   # True
$list.IndexOf("Banana")   # 1

# 排序
$list.Sort()
# ❌ 错误:不能省略泛型参数
# [Dictionary]$dict = ...

# ✅ 正确:必须指定 Key 和 Value 类型
[System.Collections.Generic.Dictionary[string, int]]$dict = 
    [System.Collections.Generic.Dictionary[string, int]]::new()

# 或者使用 New-Object (旧式)
$dict = New-Object 'System.Collections.Generic.Dictionary[string,int]'

# 初始化时添加数据
$dict = [System.Collections.Generic.Dictionary[string, string]]::new(
    @{
        Name = "Admin"
        Role = "Manager"
    }
)

自定义对象 (PSCustomObject)

$obj = [PSCustomObject]@{
    Name  = "Server01"
    IP    = "192.168.1.1"
    Status = "Online"
}

# 访问
$obj.Name

# 导出
$obj | Export-Csv -Path "servers.csv" -NoTypeInformation

class Person {
    [string]$Name
    [int]$Age
    
    Say-Hello() {
        return "Hi, I am $($this.Name)"
    }
}

$p = [Person]::new()
# 使用 New-Object
# 旧写法 (兼容 PowerShell 2.0)
$list = New-Object System.Collections.Generic.List[object]

# 新写法 (PowerShell 5.0+, 推荐)
$list = [System.Collections.Generic.List[object]]::new()

# 使用
$list.Add("Item 1")


$p.Name = "Tom"
$p.Say-Hello()

控制流

# If 语句
if ($count -gt 10) {
    Write-Host "Count is large"
} elseif ($count -eq 10) {
    Write-Host "Count is 10"
} else {
    Write-Host "Count is small"
}

# ForEach 循环 (遍历对象)
foreach ($proc in Get-Process) {
    if ($proc.CPU -gt 100) {
        Write-Host $proc.Name
    }
}

# While 循环
$i = 0
while ($i -lt 5) {
    $i++
}

# switch
switch ($value) {
    1 { "One" }
    2 { "Two" }
    default { "Other" }
}

输出 (Output)

函数

function Invoke-MyTask {
    [CmdletBinding()]  # 启用高级功能
    param (
      [Parameter(Mandatory=$true, ValueFromPipeline=$true)]  # 1. 参数属性 (Attribute)
      [ValidateNotNullOrEmpty()]                             # 2. 验证属性 (Validation)
      [string]                                               # 3. 类型约束 (Type)
      $Path                                                  # 4. 变量名 (Variable)
    )
    
    Write-Verbose "正在处理路径:$Path" # 只有加 -Verbose 时才显示
    
    if ($PSCmdlet.ShouldProcess($Path)) { # 支持 -WhatIf 模拟运行
        Write-Output "处理完成:$Path"
    }
}

函数返回值 (Return vs Output)

# 正确做法
function Get-Data {
    $data = "Some Data"
    $data  # 隐式输出,等价于 Write-Output $data
}

# 错误做法 (在管道中会中断)
function Get-Data-Bad {
    return "Some Data" 
}

命名规范

函数调用

$cmd = "Get-Process"
& $cmd  # 执行变量里的命令

& { param($a) $a * 2 } 10  # 调用匿名脚本块,输出 20
# 定义参数包
$params = @{
    Path = "C:\Windows"
    Filter = "*.exe"
    Recurse = $true
    ErrorAction = "SilentlyContinue"
}

# 调用时注意用 @ 而不是 $
Get-ChildItem @params 

实用命令

# 发起GET请求
$response = Invoke-WebRequest -Uri "http://47.122.65.237:3000/DocPreview/api/html-files"
# 显示响应内容
$response.Content
# 将响应内容转换为 json 对象
$jsonResponse = ConvertFrom-Json $response.Content
# 访问对象属性
$jsonResponse.Backend
# 设置请求时间
$response = Invoke-WebRequest -Uri "http://www.example.com" -TimeoutSec 30

# POST 请求
# 创建请求体
$body = @{
    key1 = "value1"
    key2 = "value2"
} | ConvertTo-Json
# 设置请求头
$headers = @{
    'Content-Type' = 'application/json'
}
# 发起POST请求
$response = Invoke-WebRequest -Uri "http://www.example.com/api" -Method POST -Body $body -Headers $headers

# 自定义请求参数:
# 设置请求头
$headers = @{
    'Authorization' = 'Bearer your-access-token'
    'Content-Type' = 'application/json'
}

# 设置请求体
$body = @{
    username = "your_username"
    password = "your_password"
} | ConvertTo-Json
# 发起带有认证信息的POST请求
$response = Invoke-WebRequest -Uri "http://www.example.com/api/login" -Method POST -Body $body -Headers $headers
# 列出可用版本
winget search Microsoft.PowerShell

# 安装最新稳定版
winget install --id Microsoft.PowerShell --source winget

# 安装预览版
winget install --id Microsoft.PowerShell.Preview --source winget
# 显示所有正在监听的端口及对应进程
Get-NetTCPConnection | Where-Object { $_.State -eq 'Listen' } | Select-Object LocalPort, OwningProcess | Sort-Object LocalPort | Format-Table

# 检查端口 8080 是否被占用
$port = 8080
$process = Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue
if ($process) {
    Write-Host "端口 $port 被以下进程占用:" -ForegroundColor Red
    $process | Format-Table LocalPort, OwningProcess, State -AutoSize
} else {
    Write-Host "端口 $port 未被占用" -ForegroundColor Green
}

# 根据端口号查找进程名称和路径
$port = 8080
$pid = (Get-NetTCPConnection -LocalPort $port -ErrorAction SilentlyContinue).OwningProcess
if ($pid) {
    Get-Process -Id $pid | Select-Object Id, ProcessName, Path
}

# 强制结束占用 8080 端口的进程
$port = 8080
$pid = (Get-NetTCPConnection -LocalPort $port).OwningProcess
if ($pid) {
    Stop-Process -Id $pid -Force
    Write-Host "已终止进程 (PID: $pid)" -ForegroundColor Yellow
}