Obsługa błędów w poleceniach Exchange’a

9 lutego 2016 at 11:00

Każdy posługujący się w miarę swobodnie powershell’em administrator zna sposoby wychwytywania i obsługi błędów pojawiających się podczas wykonywania skryptów. Wśród nich „króluje” często metoda „try/catch”, która w skrócie wygląda mniej więcej tak:

ww. narzędzie jest bardzo przydatne, elastyczne i pozwalające na bardzo zaawansowane rozróżnianie i obsługę poszczególnych błędów, zwłaszcza, gdy do sekcji „catch” dodamy typ błędu, który chcemy obsłużyć np:

Z czym natomiast spotyka się niemal każdy początkujący administrator próbujący budować swoje skrypty używając metody „try/catch”? Z faktem, że cześć błędów nie jest wychwytywana…

Dlaczego tak się dzieje?

Najczęstszymi powodami są:

  • Niepoprawna akcja przy napotkaniu błędu (polecenia obsługujące przełącznik „-ErrorAction”, powinny mieć ustawioną akcję na „stop”)
  • Niepoprawne preferencje obsługi błędów dla danego zakresu ($ErrorActionPreference powinno być ustawione na „stop”)

A, że administrator nie lubi jak mu wyskakują błędy, to ustawia sobie ww. wartości na „SilentlyContinue” / „Continue” i w momencie, gdy dorośnie do obsługi błędów zaczyna ostre debugowanie.. :)

Sprawa natomiast wygląda ciekawiej w przypadku poleceń Exchange’a, które są wykonywane zdalnie w ramach sesji z serwerami Exchange’a.

W takim wypadku praca z powershell’em + modułami Exchange’a i nawiązanie sesji wygląda mniej więcej tak:

Dodaliśmy sobie przystawkę, nawiązaliśmy sesję, ustawiliśmy preferencje obsługi błędów i testujemy interaktywnie na konsoli obsługę błędów i tak jak przypuszczaliśmy działa poprawnie:

Zwraca na konsoli obsłużony błąd w postaci informacji : „Nie ma skrzynki”. Zadowoleni, że działa zapisujemy polecenie do skryptu *.ps1 – uruchamiamy i… Nie działa (!) albo w najlepszym wypadku nie zawsze działa zgodnie z oczekiwaniami, bo zwraca standardową informacje o napotkanym błędzie, zamiast naszego ładnego komunikatu o braku skrzynki :(

Co zrobić? Jak żyć?

Zamiast używać samej funkcji proxującej możemy użyć wywołania polecenia w następujący sposób:

I parafrazując popularną reklamę zostać „bohaterem w swojej firmie” 😉 Czy aby na pewno…?

Dla osób bardziej dociekliwych i tych, który nie czują różnicy pomiędzy dwoma prezentowanymi sposobami wykonania poleceń:

  • Get-Mailbox i podobne funkcje nie są w rzeczywistości wywoływanym poleceniem, lecz funkcją proxującą wykonująca pewne działania w ramach nawiązanej sesji. Nie wierzycie? Zobaczcie definicję funkcji:

Teraz już widać różnicę. Czy natomiast jest to rozwiązanie satysfakcjonujące? To zależy kogo i czego oczekujemy. Mnie to raczej nie satysfakcjonuje… Dlaczego?

Otóż prezentowany wyżej sposób jest jedynie obejściem problemu, który nie do końca go rozwiązuje, bo:

  • Sesje Exchange’owe są domyślnie nawiązywane w trybie „No Language
  • Z wyżej wymienionego faktu wynika brak zmiennych, script-block’ów, przypisań…
  • Z wyżej wymienionego faktu wynika, że podawane dane są typu „string”, więc podając „Identity” skrzynki – przetwarzany jest ciąg znaków.
  • Z wyżej wymienionego faktu wynika, że podanie jakiejkolwiek zmiennej w wywoływanym Script-Block’u skończy się nieoczekiwanym zachowaniem = przetworzeniem zmiennej jako ciągu znaków
  • ww. Jest kompletnie nieprzydatne dla zaawansowanych czynności

I przedstawiany „bohater swojej firmy” okazuje się nie być bohaterem… :(

Czy jednak można temu zaradzić? Oczywiście gdyby nie było można to nie byłoby niniejszego wpisu :) Aby poprawić beznadziejną sytuację należy zmienić tryb języka na serwerach Exchange’a.

Można to wykonać na następujący sposób:

  • Na serwerach CAS’owych uruchomić konsolkę zarządzania serwerem aplikacji (IIS Manager)
  • Rozwinąć węzeł serwera, przejść do stron (Sites), rozwinąć domyślną stronę (default Web Site) i kliknąc w „Powershell”
  • Przejść do ustawień aplikacji

ExchIIS1

  • Przejść do ustawień aplikacji i zmienić tryb języka na pełny (FullLanguage):

ExchIIS2

Ewentualnie w sposób opisywany kiedyś przy innej okazji: http://mkrzanowicz.pl/?p=231

Czemu nie jest to robione domyślnie? Ze względów bezpieczeństwa. Przy zmianie wykonanej jak wyżej dobrą praktyką jest ograniczenie dostępu do serwerów na poziomie sieciowym i/lub aplikacyjnym, żeby nie było to jedynie obniżenie bezpieczeństwa, lecz zastąpienie jednego mechanizmu innym, zgodnie z zasadą defence-in-depth.

Powodzenia w wychwytywaniu i obsłudze błędów (również/zwłaszcza) Esxchange’owych :)