jedną z kluczowych części każdego dobrego skryptu PowerShell jest obsługa błędów. Nawet w najkrótszym skrypcie możliwość obsługi błędów pomaga zapewnić, że nieoczekiwane zdarzenie nie zniszczy systemu, nad którym pracujesz. Weźmy przykład poniżej. Co tydzień w naszej przykładowej firmie (MyCompany.Com) Dział Kadr prześle nam listę informującą, kto powinien mieć dostęp do bazy wydatków., Jeśli na liście nie ma nazwy z HR, usuniemy ją z grupy i ten użytkownik nie będzie już mógł logować reklamacji wydatków:
teraz możesz zobaczyć, gdzie to pójdzie nie tak. W ciągu tygodnia HR nie będzie mógł przesłać listy lub, gdy już będziemy mieli dostęp do listy, serwer plików umrze. Nagle PowerShell rzuca błąd na cmdlet Get-Content i zmienna $ AuthorizedUser pozostaje pusta. Ponieważ nasz skrypt nie obsługuje błędów, nadal działa i w bardzo krótkim czasie usunął każdego użytkownika z naszej grupy wydatków., Wkrótce zaczynają zalewać się irytujące telefony, a życie staje się trochę mniej szczęśliwe. Sposobem na uniknięcie tego wszystkiego jest wychwycenie błędów, a następnie obsłużenie zdarzenia, które je spowodowało(co w tym przypadku polega na zatrzymaniu skryptu i wywołaniu krzyku na kogoś w HR).
błędy kończące i nie kończące
jedną z kluczowych rzeczy, które należy wiedzieć podczas wyłapywania błędów, jest to, że domyślnie można wyłapać tylko niektóre błędy. Błędy występują w dwóch typach-kończący i nie kończący. Błąd zakończenia to błąd, który zatrzyma funkcję lub operację., Jeśli popełnisz błąd składni lub zabraknie pamięci, jest to błąd kończący. Błędy kończące mogą być wychwytywane i obsługiwane. Błędy niezakończone umożliwiają kontynuację Powershell i zwykle pochodzą z cmdletów lub innych zarządzanych sytuacji. W normalnych okolicznościach nie można ich złapać przez Try-Catch-Finally. Błąd Get-Content w powyższym przykładzie jest błędem niekończącym się.
traktowanie błędów nie kończących się jako zakończonych
więc jak wyłapać błąd nie kończący się? Zasadniczo mówisz PowerShell, aby traktował to jako zakończenie. W tym celu należy użyć parametru ErrorAction., Każdy cmdlet PowerShell obsługuje ErrorAction. Poprzez podanie-ErrorAction Stop na końcu cmdleta upewniasz się, że wszystkie błędy, które wyrzuca są traktowane jako kończące i mogą zostać przechwycone. W powyższym przykładzie zmienimy naszą linię Get-Content NA:
$AuthorizedUsers= Get-Content \\ FileServer\HRShare\UserList.txt -ErrorAction Stop
traktując wszystkie błędy jako kończące
możliwe jest również traktowanie wszystkich błędów jako kończących za pomocą zmiennej ErrorActionPreference. Możesz to zrobić zarówno dla skryptu, z którym pracujesz, jak i dla całej sesji PowerShell. Aby ustawić go w skrypcie, wykonaj pierwszą linię $ErrorActionPreference = Stop., Aby ustawić go dla sesji, wpisz $ErrorActionPreference = Stop w konsoli PowerShell.
Przechwytywanie błędu zakończenia
Po upewnieniu się, że błąd, który próbujesz złapać, będzie traktowany jako zakończenie, możesz zbudować blok Try Catch wokół polecenia (lub poleceń), które mogą spowodować błąd. Pierwszym etapem jest otaczanie sekcji skryptu, która może spowodować błąd blokiem próby. W naszym przykładzie linia Get-Content staje się:
Try{ $AuthorizedUsers= Get-Content \\ FileServer\HRShare\UserList.txt -ErrorAction Stop}
natychmiast po bloku Try musisz umieścić blok Catch, aby poradzić sobie z błędem., Blok Catch jest dostępny tylko wtedy, gdy wystąpi błąd zakończenia, w przeciwnym razie jest ignorowany. W naszym przykładzie wyślemy wiadomość e-mail do administratora, aby powiedzieć, że wystąpił błąd, a następnie zatrzymać skrypt. Nasza linia Get-Content to teraz:
dostęp do rekordu błędu
gdy znajdujesz się wewnątrz bloku catch, możesz uzyskać dostęp do rekordu błędu, który jest przechowywany w bieżącej zmiennej obiektowej $_. Rekordy błędów mają różne użyteczne właściwości, ale główną, do której chcesz uzyskać dostęp, jest $_.Wyjątek., Wyjątki są tym, z czym tak naprawdę mamy do czynienia, ponieważ łapiemy i radzimy sobie z błędami – wyjątki są nieoczekiwanym zdarzeniem, które spowodowało błąd(sam rekord błędu jest tak naprawdę tylko opakowaniem do przedstawienia wyjątku użytkownikowi PowerShell). Jest to wyjątek, który łapiemy i wyjątek, który zawiera wszystkie naprawdę przydatne informacje na temat problemu. Jeśli pojawił się kolejny podstawowy problem, który spowodował nasz wyjątek, jest on również rejestrowany pod adresem $_.wyjątek.innerexception (i tak dalej – następny podstawowy wyjątek jest przechowywany w $_.wyjątek.innerexception.,innerexception itp.). Na potrzeby naszego przykładu użyjemy $_.Wyjątek, aby umieścić dodatkowe informacje w naszym powiadomieniu e-mail, używając $_.Wyjątek.Wiadomość i $_.Wyjątek.Właściwości ItemName:
Przechwytywanie konkretnych WYJĄTKÓW
teraz, jak pokazaliśmy w naszym przykładzie, wyłapujemy wszelkie błędy występujące podczas odczytu pliku i radzimy sobie z nimi wszystkimi w ten sam sposób. Możesz jednak wyłapać konkretne wyjątki i radzić sobie z nimi inaczej – ale-i to jest duże, ale-tylko wtedy, gdy pierwotny błąd jest zakończony., Ponieważ Get-Content cmdlet rzuca nie kończące się błędy (które potraktowaliśmy tylko jako kończące za pomocą ErrorAction), nie możemy dokładnie wyłapać różnych wyjątków, które cmdlet może wyrzucić. Jest to funkcja PowerShell i dotyczy każdego błędu nie kończącego się, niezależnie od ErrorActionPreference i nie można go zmienić. Mimo to możemy poradzić sobie z innymi wyjątkami końcowymi, takimi jak błąd braku pamięci, który może pojawić się podczas operacji odczytu. Na potrzeby tego przykładu zrobimy tak.,
wyłapujesz określone błędy kończące, podając nazwę wyjątku bezpośrednio po słowie kluczowym Catch. W naszym przykładzie chcemy złapać System.OutOfMemory wyjątek i, jeśli go uzyskamy, podejmiemy bezsensowne podejście do natychmiastowego restartowania komputera. Dodamy również ogólny blok catch po naszym pliku not found block, aby złapać wszystkie inne wyjątki:
wreszcie, używając Finally
ostatnią częścią Try Catch Finally jest blok Finally. Musi być zdefiniowana bezpośrednio po bloku Catch i uruchamiana za każdym razem, niezależnie od tego, czy wystąpił błąd, czy nie., W ten sposób można wykonywać czynności, które należy wykonać niezależnie od tego, czy operacja się powiedzie, czy nie. W naszym przykładzie będziemy rejestrować, że plik został odczytany. Nasza linia Get-Content wygląda teraz następująco: