我希望我的PowerShell脚本在我运行的任何命令失败时停止(如bash中的set -e)。我正在使用Powershell命令(New-Object System.Net.WebClient)和程序(.\setup.exe)。


当前回答

不幸的是,由于有bug的cmdlet,如New-RegKey和Clear-Disk,这些答案都不够。我目前在一个名为ps_support.ps1的文件中确定了以下代码:

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
function ThrowOnNativeFailure {
    if (-not $?)
    {
        throw 'Native Failure'
    }
}

然后在任何powershell文件中,在文件(如果存在)的CmdletBinding和Param之后,我有以下内容:

$ErrorActionPreference = "Stop"
. "$PSScriptRoot\ps_support.ps1"

重复的ErrorActionPreference = "Stop"行是有意的。如果我犯了错误,以某种方式获得了ps_support的路径。Ps1错了,那需要的不是默默的失败!

我保留ps_support。Ps1位于我的repo/workspace的公共位置,因此点源的路径可能会根据当前. Ps1文件的位置而改变。

任何本地调用都会得到这样的处理:

native_call.exe
ThrowOnNativeFailure

在编写powershell脚本时,使用该文件进行点源可以帮助我保持头脑清醒。: -)

其他回答

您应该能够通过在脚本的开头使用语句$ErrorActionPreference = "Stop"来实现这一点。

$ErrorActionPreference的默认设置是Continue,这就是为什么你看到你的脚本在错误发生后继续运行。

$ErrorActionPreference = "Stop"将得到你的部分方式(即这是cmdlets的伟大作品)。

然而,对于EXEs,你需要检查$LastExitCode自己后,每exe调用,并确定是否失败了。不幸的是,我不认为PowerShell可以在这里提供帮助,因为在Windows上,EXEs对于“成功”或“失败”退出码的构成并不是非常一致。大多数遵循UNIX标准,0表示成功,但并非所有都这样做。在这篇博客文章中查看CheckLastExitCode函数。你可能会发现它很有用。

据我所知,Powershell对它调用的子程序返回的非零退出码没有任何自动处理。

到目前为止,我所知道的模仿bash -e行为的唯一解决方案是在每次调用外部命令后添加这个检查:

if(!$?) { Exit $LASTEXITCODE }

不幸的是,由于有bug的cmdlet,如New-RegKey和Clear-Disk,这些答案都不够。我目前在一个名为ps_support.ps1的文件中确定了以下代码:

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'
function ThrowOnNativeFailure {
    if (-not $?)
    {
        throw 'Native Failure'
    }
}

然后在任何powershell文件中,在文件(如果存在)的CmdletBinding和Param之后,我有以下内容:

$ErrorActionPreference = "Stop"
. "$PSScriptRoot\ps_support.ps1"

重复的ErrorActionPreference = "Stop"行是有意的。如果我犯了错误,以某种方式获得了ps_support的路径。Ps1错了,那需要的不是默默的失败!

我保留ps_support。Ps1位于我的repo/workspace的公共位置,因此点源的路径可能会根据当前. Ps1文件的位置而改变。

任何本地调用都会得到这样的处理:

native_call.exe
ThrowOnNativeFailure

在编写powershell脚本时,使用该文件进行点源可以帮助我保持头脑清醒。: -)

看来简单的重掷就行了。

param ([string] $Path, [string] $Find, [string] $Replace)
try {
  ((Get-Content -path $Path -Raw) -replace $Find, $Replace) | Set-Content -Path $Path
  Write-Output Completed.
} catch {
  # Without try/catch block errors don't interrupt program flow.
  throw
}

现在只有在成功执行之后才会出现输出Completed。