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


当前回答

看来简单的重掷就行了。

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。

其他回答

我来这里也是为了寻找同样的东西。$ErrorActionPreference="Stop"立即杀死我的shell时,我宁愿看到错误消息(暂停)之前,它终止。回到我的批处理敏感性:

IF %ERRORLEVEL% NEQ 0 pause & GOTO EOF

我发现这对我的特定ps1脚本几乎是一样的:

Import-PSSession $Session
If ($? -ne "True") {Pause; Exit}

对于powershell函数和调用exe函数,您需要稍微不同的错误处理,并且您需要确保告诉脚本的调用者它失败了。构建在Psake库的Exec之上,具有下面结构的脚本将在所有错误时停止,并可作为大多数脚本的基本模板。

Set-StrictMode -Version latest
$ErrorActionPreference = "Stop"


# Taken from psake https://github.com/psake/psake
<#
.SYNOPSIS
  This is a helper function that runs a scriptblock and checks the PS variable $lastexitcode
  to see if an error occcured. If an error is detected then an exception is thrown.
  This function allows you to run command-line programs without having to
  explicitly check the $lastexitcode variable.
.EXAMPLE
  exec { svn info $repository_trunk } "Error executing SVN. Please verify SVN command-line client is installed"
#>
function Exec
{
    [CmdletBinding()]
    param(
        [Parameter(Position=0,Mandatory=1)][scriptblock]$cmd,
        [Parameter(Position=1,Mandatory=0)][string]$errorMessage = ("Error executing command {0}" -f $cmd)
    )
    & $cmd
    if ($lastexitcode -ne 0) {
        throw ("Exec: " + $errorMessage)
    }
}

Try {

    # Put all your stuff inside here!

    # powershell functions called as normal and try..catch reports errors 
    New-Object System.Net.WebClient

    # call exe's and check their exit code using Exec
    Exec { setup.exe }

} Catch {
    # tell the caller it has all gone wrong
    $host.SetShouldExit(-1)
    throw
}

看来简单的重掷就行了。

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。

对@alastairtree的回答做了一点修改:

function Invoke-Call {
    param (
        [scriptblock]$ScriptBlock,
        [string]$ErrorAction = $ErrorActionPreference
    )
    & @ScriptBlock
    if (($lastexitcode -ne 0) -and $ErrorAction -eq "Stop") {
        exit $lastexitcode
    }
}

Invoke-Call -ScriptBlock { dotnet build . } -ErrorAction Stop

这里的关键区别是:

它使用动词-名词(模仿Invoke-Command) 暗示它在幕后使用调用操作符 模仿内置cmdlet中的-ErrorAction行为 使用相同的退出代码退出,而不是使用新消息抛出异常

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

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

if(!$?) { Exit $LASTEXITCODE }