Powershell类似于Bash的`set -e`

时间:2012-07-12 10:44:48

标签: .net bash powershell

如何让Powershell的行为像Bash一样标志为set -eset -o errexit使Bash脚本“如果一个简单的命令以非零状态退出,则立即退出”。

我认为我可以通过设置$ErrorActionPreference="Stop"来做到这一点,但这似乎不起作用。假设我有一个脚本a.ps1

$ErrorActionPreference="Stop"
& cmd /c "exit 1"
echo "cmd exited `$LastExitCode=$LastExitCode and `$?=$?"

如果我运行它

.\a. ; echo "a.ps1 exited `$LastExitCode=$LastExitCode `$?=$?"

令我惊讶的是它打印

cmd exited $LastExitCode=1 and $?=False
a.ps1 exited $LastExitCode=1 $?=True

发生了什么事?!我希望a.ps1在第一行之后退出,抛出错误并设置$?为假。

是否有任何官方文档解释$ ErrorActionPreference?我发现的所有内容都是关于咖啡的博客this post

1 个答案:

答案 0 :(得分:11)

$ErrorActionPreference按预期工作,只是本机程序的退出代码不如PowerShell cmdlet表现得好。

对于cmdlet,错误条件很容易确定:是否发生了异常?因此,如果Write-Host设置为$ErrorActionPreference,则以下内容无法到达Stop语句:

Write-Error blah

Get-ChildItem somepathwhichsurelydoesntexisthere

对于本机程序,退出代码零通常表示没有发生错误,但这只是一个约定,因为非零退出代码表示错误。你会说如果choice存在,退出代码为1则表示错误吗?

处理此问题的唯一可行方法是在运行本机命令后检查退出代码并在需要时自行处理。 PowerShell并不试图猜测结果意味着什么,因为在这种情况下约定不足以保证默认行为。

如果你想让生活更轻松,你可以使用一个功能:

function Invoke-NativeCommand {
  $command = $args[0]
  $arguments = $args[1..($args.Length)]
  & $command @arguments
  if (!$?) {
    Write-Error "Exit code $LastExitCode while running $command $arguments"
  }
}

但一般来说,许多程序需要不同的处理,因为它们不遵守上述惯例。