版本信息最后核对:2026-10-25
脚本要区分“可恢复的失败”和“必须停下来的失败”,要把错误写进日志、返回给调用方,或在批处理中继续处理其他对象时使用。复杂的自动化脚本、发布脚本、计划任务和被其他程序调用的入口脚本都应该显式处理错误。
简单的一次性命令不需要套 try/catch;把每条命令都包起来只会掩盖真正的问题。先判断错误的类型和传播方式,再决定捕获粒度。
Get-Item 找不到路径通常是非终止错误,必须加 -ErrorAction Stop 或改变 $ErrorActionPreference 才能被 catch。Exception、CategoryInfo、FullyQualifiedErrorId、TargetObject 和调用信息。日志里记录 FullyQualifiedErrorId 比只记 Message 更利于检索。$Error 保存最近的错误集合,$? 表示上一条命令是否成功,$LASTEXITCODE 只反映原生命令的退出码。-ErrorAction Stop 把单条命令变成终止错误,SilentlyContinue 隐藏但保留在 $Error,Ignore 连 $Error 都不写,-ErrorVariable 把错误收集到指定变量。throw 产生终止错误;exit N 结束脚本并设置退出码。高级函数用 $PSCmdlet.ThrowTerminatingError() 保留更完整的错误上下文。trap 是旧式的作用域级错误处理;finally 无论成功、失败还是提前返回都会执行,适合清理临时文件和会话。Get-Error 是 7.0 新增,能直接格式化最近的 ErrorRecord;5.1 用 $Error[0] | Format-List * -Force。$ErrorView = 'ConciseView',一行显示关键信息;5.1 默认是 NormalView。脚本不要依赖错误文本的固定格式。$PSNativeCommandUseErrorActionPreference,可让原生命令的非零退出码按 $ErrorActionPreference 处理;5.1 必须手动检查 $LASTEXITCODE。# 1. 非终止错误必须显式 Stop 才能被 catch,finally 负责清理
PS C:\> try { Get-Content C:\missing.txt -ErrorAction Stop } catch { "捕获: $($_.Exception.Message)" } finally { '清理临时资源' }
# 2. 查看最近错误的完整记录;7.x 还可以直接用 Get-Error
PS C:\> $Error[0] | Format-List * -Force
PS C:\> Get-Error
# 3. 不想中断循环,但要把错误收集起来统一判断
PS C:\> Get-ChildItem C:\NoSuchDir -ErrorAction SilentlyContinue -ErrorVariable errs
PS C:\> if ($errs.Count -gt 0) { $errs[0].CategoryInfo }
# 4. 原生命令不抛 PowerShell 异常,必须检查退出码
PS C:\> git status
PS C:\> if ($LASTEXITCODE -ne 0) { throw "git 失败,退出码 $LASTEXITCODE" }
# 5. 临时把默认行为改成终止错误,结束后恢复原值
PS C:\> $old = $ErrorActionPreference
PS C:\> $ErrorActionPreference = 'Stop'
PS C:\> try { Get-Item C:\missing } catch { $_.FullyQualifiedErrorId }
PS C:\> $ErrorActionPreference = $old
# 6. 按异常类型分别处理,不要用空 catch 吞掉所有错误
PS C:\> try { [int]::Parse('abc') } catch [System.FormatException] { '格式错误' } catch { '其他错误' }
# 7. 7.4+ 可选:让原生命令非零退出码遵循 ErrorActionPreference
PS C:\> $PSNativeCommandUseErrorActionPreference = $true
PS C:\> $ErrorActionPreference = 'Stop'
PS C:\> try { git status } catch { "git failed: $($_.Exception.Message)" }
try/catch 没有捕获到错误,通常因为它是非终止错误。给命令加 -ErrorAction Stop,或在受限作用域内临时设置 $ErrorActionPreference = 'Stop'。SilentlyContinue 不等于没发生:错误仍写入 $Error,可能影响后续判断;需要彻底忽略用 Ignore,需要记录用 -ErrorVariable。$ErrorActionPreference 通常不会改变调用方;脚本结束前恢复原值,避免影响同一会话里的后续命令。$LASTEXITCODE 只由原生命令和 exit 设置,执行一个成功 cmdlet 不会把它清零。检查前先确认上一条就是目标原生命令。2>&1 合并进成功流后,得到的是 ErrorRecord 还是字符串取决于版本和命令;下游过滤前先看对象类型,不要假设都是文本。catch { } 空实现会吞掉所有异常,包括路径写错、权限不足和语法错误。至少记录 FullyQualifiedErrorId,或只捕获明确类型。throw 'message' 丢失原始异常类型和堆栈。需要保留上下文时抛 ErrorRecord,或在 catch 中先记录再重新抛出。exit 会结束整个脚本甚至宿主会话,不是“返回函数”;函数内退出用 return,脚本入口才用 exit 设置退出码。合上页面,先回答,再展开对照。
try { Get-Item C:\missing } catch { } 没有进入 catch?-ErrorAction SilentlyContinue 和 -ErrorAction Ignore 有什么区别?Get-Item 默认产生非终止错误,只写入错误流并继续,不会触发 catch;需要加 -ErrorAction Stop 或把 $ErrorActionPreference 设为 Stop。SilentlyContinue 不显示错误但仍写入 $Error 和 -ErrorVariable;Ignore 连错误记录都不产生,适合确定要完全忽略的场景。$LASTEXITCODE 是否为 0,并确认它是目标程序刚刚设置的;PowerShell cmdlet 的失败则看 $?、错误流或 -ErrorAction Stop。
小程序版
微信扫码,随时查命令