Как остановить скрипт PowerShell при первой ошибке? - PullRequest
211 голосов
/ 30 марта 2012

Я хочу, чтобы мой скрипт PowerShell останавливался, когда любая из команд, которые я запускаю, не срабатывает (например, set -e в bash).Я использую как команды Powershell (New-Object System.Net.WebClient), так и программы (.\setup.exe).

Ответы [ 7 ]

257 голосов
/ 31 марта 2012

$ErrorActionPreference = "Stop" поможет вам в этом (например, это прекрасно работает для командлетов).

Однако для EXE вам придется проверять $LastExitCode самостоятельно после каждого вызова exe и определятьпровалилось это или нет.К сожалению, я не думаю, что PowerShell может помочь в этом, потому что в Windows EXE-файлы не очень согласуются с тем, что представляет собой код завершения «успех» или «отказ».Большинство из них следуют стандарту UNIX 0, что указывает на успех, но не все.Ознакомьтесь с функцией CheckLastExitCode в этом блоге .Вы можете найти это полезным.

61 голосов
/ 30 марта 2012

Вы должны быть в состоянии сделать это, используя оператор $ErrorActionPreference = "Stop" в начале ваших сценариев.

Значение по умолчанию $ErrorActionPreference равно Continue, поэтому вы видите свои сценариипродолжать идти после ошибок.

11 голосов
/ 28 июня 2017

К сожалению, из-за ошибочных командлетов, таких как New-RegKey и Clear-Disk , ни один из этих ответов не является достаточным.В настоящее время я остановился на следующих строках в верхней части любого сценария powershell, чтобы сохранить свое здравомыслие.

Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
$PSDefaultParameterValues['*:ErrorAction']='Stop'

, и тогда любой нативный вызов получит такую ​​обработку:

native_call.exe
$native_call_success = $?
if (-not $native_call_success)
{
    throw 'error making native call'
}

Этот нативныйшаблон вызовов постепенно становится достаточно распространенным для меня, поэтому я, вероятно, должен рассмотреть варианты, чтобы сделать его более кратким.Я все еще новичок в PowerShell, поэтому предложения приветствуются.

10 голосов
/ 27 февраля 2018

Вам нужно немного по-другому обрабатывать ошибки для функций powershell и для вызова exe, и вы должны быть уверены, что сообщили вызывающему скрипту, что он не выполнен. Построенный поверх Exec из библиотеки Psake, скрипт со структурой ниже остановит все ошибки и будет использоваться в качестве базового шаблона для большинства скриптов.

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
}
6 голосов
/ 12 октября 2018

Небольшая модификация ответа от @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

Ключевые отличия здесь:

  1. используется глагол-существительное (имитирует Invoke-Command)
  2. подразумевает, что он использует оператор вызова под прикрытием
  3. имитирует -ErrorAction поведение встроенных командлетов
  4. завершает работу с тем же кодом завершения, а не генерирует исключение с новым сообщением
2 голосов
/ 02 сентября 2017

Я пришел сюда в поисках того же. $ ErrorActionPreference = "Stop" немедленно убивает мою оболочку, когда я предпочитаю увидеть сообщение об ошибке (пауза) до его завершения. Возвращаясь к моей партии чувств:

IF %ERRORLEVEL% NEQ 0 pause & GOTO EOF

Я обнаружил, что это работает примерно так же для моего конкретного сценария PS1:

Import-PSSession $Session
If ($? -ne "True") {Pause; Exit}
0 голосов
/ 17 мая 2019

Я новичок в powershell, но это, кажется, наиболее эффективно:

doSomething -arg myArg
if (-not $?) {throw "Failed to doSomething"}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...