Powershell: Jak mogę zapobiec wyświetlaniu błędów w skrypcie?

94

Gdy mój skrypt PowerShell próbuje na przykład utworzyć obiekt SQL Server dla serwera, który nie istnieje (w moim przypadku „bla”), program PowerShell wyświetla wiele błędów programu PowerShell na czerwono.

Ponieważ mój skrypt sprawdza wartość $?po takich wywołaniach oraz wyświetla i rejestruje błędy, wolałbym nie wyświetlać również kilku wierszy błędów programu PowerShell.

Jak mogę dezaktywować te wyświetlane w moim skrypcie?

Andrew J. Brehm
źródło

Odpowiedzi:

140

Masz kilka opcji. Najłatwiej jest użyć ErrorActionustawień.

-Erroractionto uniwersalny parametr dla wszystkich poleceń cmdlet. Jeśli istnieją specjalne polecenia, które chcesz zignorować, możesz użyć, -erroraction 'silentlycontinue'które zasadniczo zignoruje wszystkie komunikaty o błędach generowane przez to polecenie. Możesz również użyć Ignorewartości (w PowerShell 3+):

W przeciwieństwie do SilentlyContinue, Ignore nie dodaje komunikatu o błędzie do zmiennej automatycznej $ Error.

Jeśli chcesz zignorować wszystkie błędy w skrypcie, możesz użyć zmiennej systemowej $ErrorActionPreferencei zrobić to samo:$ErrorActionPreference= 'silentlycontinue'

Zobacz about_CommonParameters, aby uzyskać więcej informacji o -ErrorAction. Zobacz about_preference_variables, aby uzyskać więcej informacji na temat $ ErrorActionPreference.

JNK
źródło
czy potrzebujesz pojedynczego cudzysłowu w przypadku błędu „silentlycontinue”? Intellisese pokazuje opcje i nie dodaje pojedynczego cudzysłowu.
PAS
1
Jeśli powyższy format nie działa dla Ciebie, skorzystaj z linku podanego powyżej. Musiałem sformatować jak -ErrorAction:SilentlyContinuew PS 5.1. Dzwoniłem do mojego polecenia cmdlet z partii, więc nie wiem, czy to robi różnicę. Ale dobre informacje, gdy wiesz, że dopuszczalny błąd mogą zostać wyrzucone.
David
--rm. \ Windows.old \ -Force -Recurse -Verbose -ErrorAction SilentlyContinue -WarningAction SilentlyContinue </code>
Tertius Geldenhuys
18

Program Windows PowerShell udostępnia dwa mechanizmy raportowania błędów: jeden mechanizm przerywania błędów i drugi mechanizm niepowodujący zakończenia błędów .

Kod wewnętrzny CmdLets może wywołać ThrowTerminatingErrormetodę, gdy wystąpi błąd, który nie pozwala lub nie powinien zezwalać cmdletowi na dalsze przetwarzanie jego obiektów wejściowych. Osoba pisząca skrypt może użyć wyjątku, aby wyłapać te błędy.

EX:

try
{
  Your database code
}
catch
{
  Error reporting/logging
}

Wewnętrzny kod CmdLets może wywołać WriteErrormetodę w celu zgłoszenia błędów niepowodujących zakończenia, gdy polecenie cmdlet może kontynuować przetwarzanie obiektów wejściowych. Twórca skryptu może następnie użyć opcji -ErrorAction, aby ukryć komunikaty, lub użyć $ErrorActionPreferencedo ustawienia zachowania całego skryptu.

JPBlanc
źródło
8

Miałem podobny problem, gdy próbowałem rozwiązać nazwy hostów za pomocą [system.net.dns]. Jeśli adres IP nie został rozwiązany .Net wyrzucił błąd powodujący zakończenie. Aby zapobiec błędowi kończącemu i nadal zachować kontrolę nad wyjściem, utworzyłem funkcję przy użyciu TRAP.

NA PRZYKŁAD

Function Get-IP 
{PARAM   ([string]$HostName="")
PROCESS {TRAP 
             {"" ;continue} 
             [system.net.dns]::gethostaddresses($HostName)
        }
}
DW
źródło
3

Jesteś daleko od celu.

Masz już ładny, duży komunikat o błędzie. Dlaczego na Ziemi miałbyś chcieć napisać kod, który sprawdza $?jawnie po każdym poleceniu ? Jest to niezwykle uciążliwe i podatne na błędy. Prawidłowym rozwiązaniem jest zaprzestanie sprawdzania$? .

Zamiast tego użyj wbudowanego mechanizmu PowerShell, aby wysadzić w powietrze. Możesz to włączyć, ustawiając preferencję błędu na najwyższy poziom:

$ErrorActionPreference = 'Stop'

Umieszczam to na początku każdego skryptu, który kiedykolwiek napisałem, i teraz nie muszę tego sprawdzać $?. To sprawia, że ​​mój kod jest znacznie prostszy i bardziej niezawodny.

Jeśli napotkasz sytuacje, w których naprawdę musisz wyłączyć to zachowanie, możesz albo catchbłąd, albo przekazać ustawienie do określonej funkcji przy użyciu funkcji common -ErrorAction. W Twoim przypadku prawdopodobnie chcesz, aby proces zatrzymał się przy pierwszym błędzie, złapał błąd, a następnie zarejestrował go.

Zwróć uwagę, że nie obsługuje to przypadku, gdy zewnętrzne pliki wykonywalne zawodzą (zwykle kod zakończenia niezerowy), więc nadal musisz sprawdzić, $LASTEXITCODEczy któreś wywołujesz. Pomimo tego ograniczenia, ustawienie nadal oszczędza dużo kodu i wysiłku.

Dodatkowa niezawodność

Możesz również rozważyć użycie trybu ścisłego :

Set-StrictMode -Version Latest

Zapobiega to dyskretnemu kontynuowaniu programu PowerShell, gdy używasz nieistniejącej zmiennej oraz w innych dziwnych sytuacjach. (Zobacz -Versionparametr, aby uzyskać szczegółowe informacje o tym, co ogranicza).

Połączenie tych dwóch ustawień sprawia, że ​​PowerShell jest znacznie bardziej odporny na awarie, co znacznie ułatwia programowanie w nim.

jpmc26
źródło
2

Dodaj -ErrorAction SilentlyContinuedo swojego scenariusza, a będziesz gotowy.

Jayant Rajwani
źródło
2

W niektórych przypadkach można potokować po poleceniu Out-Null

command | Out-Null
Jagoda
źródło
-1

Jeśli chcesz, aby komunikat o błędzie programu PowerShell dla polecenia cmdlet został pominięty, ale nadal chcesz go wychwycić, użyj opcji „-erroraction 'silentlyStop'”

Mikkel Vejlby
źródło
Nie ma takiego działania. Chociaż istnieje akcja Stop.
Marvin Dickhaus
Ale pozwala to pominąć czerwony komunikat o błędzie i nadal używać polecenia catch / sekcji podczas korzystania z New-Item -ItemType directory(PowerShell v2.0)
Milan Kerslager
@MilanKerslager, czy mógłbyś uprzejmie pokazać przykład kodu - ponieważ ja i wszyscy inni wierzymy, że nie ma takiej ActionPreference jak „
SilentlyStop
Jestem dość przekonany, że Mikkel miał na myśli SilentlyContinue, a nie cichoStop, ponieważ ma to o wiele większy sens w treści tego, co chcesz, aby robił.
John