[Powershell入门教程]第4天:模块、脚本编写、错误处理与 .NET 集成
第4天:模块、脚本编写、错误处理与 .NET 集成
🎯 学习目标
- 掌握 PowerShell 脚本(
.ps1)的结构与最佳实践 - 理解模块(Module)的作用,并能创建和导入自定义模块
- 熟练使用
try/catch/finally进行结构化错误处理 - 直接调用 .NET 类库(如
System.IO,System.Net等)完成高级任务
一、PowerShell 脚本编写(.ps1 文件)
1. 脚本基本结构
一个良好的脚本应包含:
- 注释说明(用途、作者、参数)
- 参数声明(
param块) - 错误处理(
$ErrorActionPreference或try/catch) - 主逻辑
- 清理或输出
# Get-DiskUsage.ps1
<#
.SYNOPSIS获取指定目录的磁盘使用情况。
.DESCRIPTION计算目录下所有文件总大小,支持递归。
.PARAMETER Path目标路径,默认为当前目录。
.EXAMPLE.\Get-DiskUsage.ps1 -Path C:\Temp
#>param([string]$Path = "."
)if (-not (Test-Path $Path)) {throw "路径不存在: $Path"
}$totalBytes = (Get-ChildItem -Path $Path -Recurse -File | Measure-Object -Property Length -Sum).Sum
"{0:N2} MB" -f ($totalBytes / 1MB)💡 使用方式:
.\Get-DiskUsage.ps1 -Path C:\Windows
2. 脚本执行方式回顾
| 方式 | 命令 | 说明 |
|---|---|---|
| 当前作用域运行 | . .\script.ps1 | 变量/函数留在当前会话(点源执行) |
| 子作用域运行 | .\script.ps1 | 执行完后环境不保留 |
| 绕过策略运行 | PowerShell -ExecutionPolicy Bypass -File script.ps1 | 适合自动化 |
二、模块(Modules)——组织可重用代码
1. 什么是模块?
模块是 PowerShell 中用于封装函数、变量、别名等的单元,便于分发和复用。
内置模块示例:
Get-Module -ListAvailable # 查看所有可用模块
Import-Module ActiveDirectory # 导入 AD 模块(需安装)2. 创建自定义模块
步骤1:创建模块目录
C:\Users\<username>\Documents\Documents\WindowsPowerShell\PowerShell\Modules\MyTools\
└── MyTools.psm1 ← 模块主文件⚠️ 路径必须在
$env:PSModulePath中(用户模块默认在此)⚠️ 可能次路径不存在,需手动建立
步骤2:编写 MyTools.psm1
# MyTools.psm1
function Get-Uptime {$os = Get-CimInstance Win32_OperatingSystem(Get-Date) - $os.LastBootUpTime
}function Test-Port {param([string]$ComputerName, [int]$Port)try {$tcp = New-Object System.Net.Sockets.TcpClient$tcp.Connect($ComputerName, $Port)$tcp.Connected$tcp.Close()} catch {$false}
}Export-ModuleMember -Function Get-Uptime, Test-Port步骤3:导入并使用
Import-Module MyTools
Get-Uptime
Test-Port -ComputerName "baidu.com" -Port 80✅ 优势:函数自动加载,命名空间清晰,易于共享。
三、错误处理:try / catch / finally
PowerShell 支持结构化异常处理,但需注意:
- 仅对“终止性错误”(Terminating Errors)生效
- 默认很多命令产生的是“非终止错误”(如
Get-Item NoSuchFile)
1. 强制将错误转为终止错误
使用 -ErrorAction Stop:
try {Get-Item "C:\NonExistentFile.txt" -ErrorAction Stop
} catch {Write-Host "捕获到错误: $($_.Exception.Message)" -ForegroundColor Red
} finally {Write-Host "清理操作(无论成功与否都会执行)"
}
2. 捕获特定异常类型(.NET 集成)
你可以根据 .NET 异常类型进行精细处理:
try {[System.IO.File]::ReadAllText("C:\Protected\file.txt")
} catch [System.UnauthorizedAccessException] {Write-Host "权限不足!" -ForegroundColor Yellow
} catch [System.IO.FileNotFoundException] {Write-Host "文件未找到!" -ForegroundColor Cyan
} catch {Write-Host "未知错误: $($_.Exception.GetType().FullName)"
}🔍 提示:通过
$_.Exception.GetType().FullName查看具体异常类型。
四、PowerShell 与 .NET 深度集成(核心优势!)
PowerShell 基于 .NET(Windows 上是 .NET Framework/.NET,跨平台是 .NET Core),可直接调用任何 .NET 类。
1. 调用静态方法
# 获取当前时间(等价于 Get-Date)
[System.DateTime]::Now# 生成 GUID
[System.Guid]::NewGuid()# 环境信息
[System.Environment]::OSVersion
[System.Environment]::GetFolderPath("Desktop")2. 创建 .NET 对象实例
# 创建 WebClient(已过时,推荐使用 Invoke-WebRequest)
$client = New-Object System.Net.WebClient
$content = $client.DownloadString("https://httpbin.org/ip")
$client.Dispose() # 释放资源✅ 更现代的方式(PowerShell 5+):
Invoke-RestMethod https://httpbin.org/ip
3. 使用 .NET 枚举
# 文件属性
$file = Get-Item .\test.txt
$file.Attributes -band [System.IO.FileAttributes]::Hidden4. 调用 .NET 方法处理字符串/数学
# 字符串操作(比 PowerShell 内置更强大)
[System.String]::IsNullOrWhiteSpace(" ") # True# 数学计算
[Math]::Round(3.14159, 2) # 3.14
[Math]::Pow(2, 10) # 10245. 实战:用 .NET 发送邮件(无需 Outlook)
$smtp = New-Object Net.Mail.SmtpClient("smtp.example.com", 587)
$smtp.EnableSsl = $true
$smtp.Credentials = [Net.NetworkCredential]::new("user@example.com", "password")$mail = [Net.Mail.MailMessage]::new("from@example.com", "to@example.com", "主题", "正文")
$smtp.Send($mail)
$smtp.Dispose()⚠️ 注意:生产环境建议使用安全凭据(如
$PSCredential)。
五、动手实践:综合项目
项目:编写一个带错误处理的“网站健康检查”脚本
# HealthCheck.ps1
param([string[]]$Urls = @("https://baidu.com", "https://github.com")
)foreach ($url in $Urls) {try {Write-Host "正在检查: $url" -ForegroundColor Green$response = Invoke-WebRequest -Uri $url -UseBasicParsing -TimeoutSec 10if ($response.StatusCode -eq 200) {Write-Host "✅ 正常 (状态码: $($response.StatusCode))"} else {Write-Host "⚠️ 异常状态码: $($response.StatusCode)" -ForegroundColor Yellow}} catch {$ex = $_.Exceptionif ($ex -is [System.Net.WebException]) {Write-Host "❌ 网络错误: $($ex.Message)" -ForegroundColor Red} else {Write-Host "💥 未知错误: $($ex.Message)" -ForegroundColor Magenta}}
}运行:
.\HealthCheck.ps1 -Urls "https://baidu.com", "https://nonexistent.fake"六、今日重点总结
- ✅ 脚本应结构清晰,包含参数、注释和错误处理
- ✅ 模块(
.psm1)是组织可重用函数的最佳方式 - ✅
try/catch需配合-ErrorAction Stop或 .NET 异常使用 - ✅ PowerShell 是 .NET 的“脚本前端”,可直接调用任何 .NET 类库
- ✅ 利用
[System.xxx]和New-Object解锁高级功能(网络、文件、加密等)
📚 参考资料(Microsoft Learn)
- About Modules
- About Try Catch Finally
- Calling .NET Methods
- .NET API Browser
🏁 课后作业
- 创建一个名为
MathUtils的模块,包含两个函数:Convert-Temperature(℃↔℉)和Get-Factorial(阶乘,用递归或 .NETBigInteger)。 - 编写脚本:尝试读取一个受保护的系统文件(如
C:\Windows\System32\config\SAM),使用try/catch捕获UnauthorizedAccessException并友好提示。 - 使用 .NET 的
System.IO.Compression.ZipFile类,编写一个函数Compress-Folder,将指定文件夹压缩为 ZIP。
