catchAllTheErrors-615x461obsługa błędu może przyprawić nieco problemu, dla tego kilka zebranych tips’n’tricks, które mogą się przydać.

try/catch nie działa!

czasem nie działa. a to dla tego, że klauza catch zostanie wykonana dla błędów ‘terminujących’. większość błędów natomiast jest ‘zwykłymi’ błędami, nieterminującymi. zachowanie można zmienić albo zmieniając standardowe zachowanie poprzez globalnie ustawienie zmiennej

$ErrorActionPreference="stop"

co spowoduje nadpisanie wartości ustawionych dla commandletu.

można też po prostu dodać parametr ‘-ea’ dla konkretnego wywołania. przykład. to nie zadziała zgodnie z oczekiwaniami:

try { gwmi -class win32_bios -ComputerName tralla} catch { echo 'TU NIE DZIAŁA'}

napis ‘tu nie działa’ nigdy się nie pojawi. poprawiona wersja:

try { gwmi -class win32_bios -ComputerName tralla -ea stop} catch { echo "TU NIE DZIAŁA" }

zapytanie reqrsywne

problem z takim wymuszeniem jest w przypadq zapytań reqrsywnych. scenariusz: chciałbym wyszukać wszystkie katalogi, do których nie mam dostępu. robię reqrsywne przejście po katalogach i ustawiam błąd jako terminujący:

try { ls -Recurse -Directory C:\Windows\ -ea stop|out-null} catch { write-host "TU NIE DZIAŁA!" }

niby działa… ale, błąd jest terminujący. co oznacza, że po pierwszym wystąpieniu zakończy działanie wykonania. zobaczymy tylko pierwszy katalog, do którego nie mamy dostępu.

należy skorzystać z innej metody – przekazania błędów do zmiennej. uzysqje się to poprzez parametr ‘ErrorValue’ [alias ‘ev’]. wada jest taka, że zmienna zwracana jest po zakończeniu działania. tutaj już nie ma try/catch!

ls -Recurse -Directory C:\Windows\ -ev LISTINGERRORS|out-null
foreach($lerr in $LISTINGERRORS) {
    write-host "TU NIE DZIAŁA!"
    $lerr
}

oczywiście jeśli nie chce się oglądać błędów z przebiegu, to można sobie dodać ‘-ea SilentlyContinue’ .

szczegóły błędu

na ekranie nadal będzie śmietnik. fajnie byłoby złapać tylko nazwy – i np. dla nich coś wykonać. dla tego warto zapoznać się z obiektem błędu:

   TypeName: System.Management.Automation.ErrorRecord

Name                  MemberType     Definition
----                  ----------     ----------
Equals                Method         bool Equals(System.Object obj)
GetHashCode           Method         int GetHashCode()
GetObjectData         Method         void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System....
GetType               Method         type GetType()
ToString              Method         string ToString()
CategoryInfo          Property       System.Management.Automation.ErrorCategoryInfo CategoryInfo {get;}
ErrorDetails          Property       System.Management.Automation.ErrorDetails ErrorDetails {get;set;}
Exception             Property       System.Exception Exception {get;}
FullyQualifiedErrorId Property       string FullyQualifiedErrorId {get;}
InvocationInfo        Property       System.Management.Automation.InvocationInfo InvocationInfo {get;}
PipelineIterationInfo Property       System.Collections.ObjectModel.ReadOnlyCollection[int] PipelineIterationInfo {g...
ScriptStackTrace      Property       string ScriptStackTrace {get;}
TargetObject          Property       System.Object TargetObject {get;}
PSMessageDetails      ScriptProperty System.Object PSMessageDetails {get=& { Set-StrictMode -Version 1; $this.Except...

teraz widać co mamy do dyspozycji. wyjątkowo ciekawe do obsługi będą ‘FullyQualifiedErrorId’ pozwalający na zdefiniowanie logiki zależnie od rodzaju błędu, oraz ‘TargetObject’ gdzie powinna znaleźć się informacja o obiekcie, który wygenerował błąd. proponuję przetestować, bo tak najlepiej się uczyć:

ls -Recurse -Directory C:\Windows\ -ev LISTINGERRORS -ea SilentlyContinue|out-null
foreach($lerr in $LISTINGERRORS) {
    write-host $lerr.TargetObject
}

nie wszystko jest błędem

i na koniec – nie wszystko co my uważamy za błąd, jest błędem. nie mam teraz przygotowanego przykładu, niemniej zdarzało mi się, że commandlet zwracał null lub informował o niepowodzeniu – co było jak najbardziej prawidłowym zachowaniem a nie błędem per se. w takim przypadq trzeba sobie obsłużyć błąd zwykłym if’em bo try/catch tego nie znajdzie.

eN.

Spread the love

Zostaw komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Time limit is exhausted. Please reload CAPTCHA.