KernelRanch
返回文章列表

PowerShell 的 try/catch 为什么漏掉了原生命令失败?

2026-11-13 #powershell#windows#ci

PowerShell 包装编译器、Git 或部署工具时,原生命令的非零退出码和 PowerShell 的异常处理取决于当前设置。需要精确解释工具退出码时,在调用后立即读取 $LASTEXITCODE,再按该工具的约定决定是否终止脚本。

1. 让同一条命令退出 7

把以下代码保存为 native_exit_lab.ps1,用 pwsh -NoProfile -File ./native_exit_lab.ps1 运行。需要 PowerShell 7.4 或更新版本和 Windows 的 cmd.exe。/d 禁止 cmd 执行自动运行命令。

$ErrorActionPreference = 'Stop'

foreach ($nativePreference in @($false, $true)) {
    $PSNativeCommandUseErrorActionPreference = $nativePreference
    $caught = $false

    try {
        cmd.exe /d /c 'exit /b 7'
    } catch {
        $caught = $true
    }

    $code = $LASTEXITCODE
    if ($code -ne 7 -or $caught -ne $nativePreference) {
        throw "Unexpected state: preference=$nativePreference caught=$caught code=$code"
    }

    "preference=$nativePreference caught=$caught exit=$code"
}

$child = '$ErrorActionPreference="Stop"; $PSNativeCommandUseErrorActionPreference=$false; cmd.exe /d /c "exit /b 7"; exit $LASTEXITCODE'
$PSNativeCommandUseErrorActionPreference = $false
pwsh -NoProfile -Command $child
$propagated = $LASTEXITCODE
if ($propagated -ne 7) {
    throw "Child exit code was $propagated"
}
"child PowerShell exit=$propagated"
preference=False caught=False exit=7
preference=True caught=True exit=7
child PowerShell exit=7

2. 明确谁解释退出码

当 $PSNativeCommandUseErrorActionPreference 为 true 时,非零退出会按 $ErrorActionPreference 处理。本例使用 Stop,因此进入 catch。设为 false 时,原生命令正常返回控制权,退出码仍由 $LASTEXITCODE 提供。后续另一条原生命令可能改写它,排障脚本应在调用后就保存。

有的工具用非零值表达差异或其他业务状态。包装这类工具时,可以在独立脚本块内将原生命令错误偏好设为 false,并根据工具文档解释每种返回值。可复用函数通常抛出异常或返回结构化结果,由脚本入口决定最终进程退出码。CI 若需要原样接收某个失败码,由入口执行 exit $code,并像样本一样从父进程验证。

小结

在原生命令调用处保存退出码,在脚本边界明确失败如何上报。try/catch 的表现要和偏好设置一起读。

数据来源与检索时间

来源URL检索日期对应内容
Microsoft Learn about_Automatic_Variableshttps://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_automatic_variables?view=powershell-7.5#lastexitcode2026-11-13LASTEXITCODE 的来源及脚本退出行为
Microsoft Learn about_Preference_Variableshttps://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7.5#psnativecommanduseerroractionpreference2026-11-13非零退出码如何遵循 ErrorActionPreference

核验说明

  • Windows、PowerShell 7.6.9 实测两种偏好设置与子进程退出码。示例使用确定性的 cmd 子进程,具体业务工具仍需按其退出码文档处理。