2012-07-12 12 views
5

Jak mogę sprawić, aby Powershell zachowywał się jak Bash z flagą set -e? set -e tworzy skrypt Bash "Wyjdź natychmiast, jeśli proste polecenie zostanie zakończone ze statusem niezerowym".Powershell analogiczny z Bash `set -e`

Pomyślałem, że mogę to zrobić, ustawiając $ErrorActionPreference="Stop", ale to nie działa. Załóżmy, że mam skryptu a.ps1

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

Jeśli go uruchomić

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

Do moich niespodzianek drukuje

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

Co się dzieje ?! Oczekuję, że a.ps1 wyjdzie po pierwszym wierszu, rzucając błąd i ustawiając $? do fałszywego.

Czy istnieje oficjalna dokumentacja wyjaśniająca $ ErrorActionPreference? Wszystko, co znalazłem, to this post na blogu o kawie.

Odpowiedz

9

$ErrorActionPreference działa zgodnie z przeznaczeniem, po prostu kody wyjścia z programów macierzystych nie są tak dobrze zachowane, jak polecenia cmdlet programu PowerShell.

Dla błędu cmdlet stan błędu jest dość łatwy do ustalenia: Czy wystąpił wyjątek, czy nie? Więc dodaje się nie osiągnie oświadczenie Write-Host z $ErrorActionPreference zestaw do Stop:

Write-Error blah 

lub

Get-ChildItem somepathwhichsurelydoesntexisthere 

Dla programów rodzimych kod wyjścia zero zwykle sygnały, że nie wystąpił błąd, ale to tylko konwencja, podobnie jak niezerowy kod wyjścia sygnalizujący błąd. Czy powiedziałbyś, że jeśli choice istnieje z kodem zakończenia 1, który był błędem?

Jedynym skutecznym sposobem radzenia sobie z tym problemem jest sprawdzenie kodu wyjściowego po uruchomieniu natywnego polecenia i samodzielnym jego obsłudze, w razie potrzeby. PowerShell nie próbuje odgadnąć, co oznaczało wynik, ponieważ konwencje nie są wystarczająco silne, aby zagwarantować domyślne zachowanie w tym przypadku.

Można użyć funkcji, jeśli chcesz, aby ułatwić Ci życie:

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

Ale w wielu programach ogólnych potrzebują innego traktowania, ponieważ nie przylega do wspomnianej konwencji.

+1

Shucks, to frustrujące. Dzięki za funkcję, wykorzystam to. –

+1

Ta funkcja działa świetnie. Zmieniłem test '! $?' Na '$ LastExitCode -ne 0' ponieważ' $? 'Jest zepsute http://stackoverflow.com/questions/10666101/powershell-lastexitcode-0-but-false-redirecting-stderr- to-stdout-give-nat –

+0

Tak, było. Zauważyłem również, że Twój błąd może wymagać dostosowania w każdym przypadku;) – Joey

Powiązane problemy