2012-09-25 19 views
6

Jeśli typ środowiska wykonawczego systemu Windows powoduje błąd COM .NET wydaje się często owijać ten błąd (lub zawsze?) Tylko w instancję Exception. Komunikat o błędzie zawiera kod błędu COM HRESULT. Podczas korzystania z nowego Cryptographic API z AES-CBC na przykład niewłaściwa długość bufora powoduje, że Exception z komunikatem "Dostarczony bufor użytkownika jest niepoprawny dla żądanej operacji (Exception from HRESULT: 0x800706F8)".Jak obsługiwać wyjątki WinRT, które powodują wyjątek?

Cóż, jak mamy sobie poradzić z tymi wyjątkami? Czy powinniśmy przeczytać kod od HRESULT, aby dowiedzieć się, jaki to był wyjątek? W klasycznym .NET dostałbym CryptographicException, którego mogłem użyć do odróżnienia błędów kryptograficznych od innych błędów.

Inną rzeczą, której nie rozumiem, jest to, że zasady jakości kodu Microsoft stwierdzają, że nigdy nie należy wyrzucać typów wyjątków, ale zawsze pochodnych. Powodem jest to, że nikt nie powinien być zmuszany do złapania generalnego Exception, który łapie więcej krytycznych wyjątków, takich jak OutOfMemoryException. Inna zasada mówi, że nigdy nie powinno się w żadnym razie przechwytywać bibliotek. Jak możemy postępować zgodnie z tymi zasadami, jeśli jesteśmy zmuszeni złapać Exception w aplikacjach Windows Store lub bibliotekach WinRT?

Przy okazji: Clemens Vasters shows in his blog how we can catch Exception while avoiding to catch fatal exception. Zakładam, że złapanie Exception nie jest już wtedy złym kodem.

+0

W odniesieniu do połączonego wpisu w blogu wiele wymienionych "śmiertelnych" wyjątków nie może zostać przechwyconych przez kod zarządzany. Warto zauważyć, 'StackOverflowException', chociaż jestem prawie pewien, że AVs również nie może zostać przechwycony (oba mogą być przechwycone w natywnym kodzie, oczywiście, ale jest to niebezpieczne). Zauważ też, że niektóre wyjątki, które __wyjaśniają_, mogą nie być tak naprawdę. Na przykład wiele komponentów COM zwraca 'E_OUTOFMEMORY', gdy przestrzeń w określonym buforze jest wyczerpana. HRESULT zostanie przetłumaczony jako OutOfMemoryException, ale nie oznacza to, że proces wyczerpał całą swoją przestrzeń adresową. –

Odpowiedz

4

Możliwe jest złapanie Exception, obsługa konkretnych błędów przez włączenie HRESULT i ponowne wrzucenie Exception, jeśli błąd był "nieoczekiwany". Na przykład,

try 
{ 
    // ... 
} 
catch (Exception ex) 
{ 
    switch (ex->HResult) 
    { 
    case E_INVALID_USER_BUFFER: // 0x800706f8 
     // handle invalid buffer case... 
     break; 
    default: 
     // Unexpected exception; re-throw: 
     throw; 
    } 
} 

(chciałbym zauważyć, że zapewnienie nieprawidłowy bufor brzmi bardziej jak błędu logicznego niż runtime error, więc zastanawiam się, czy ten konkretny wyjątek powinien być naprawdę złapać.)

Alternatywnie, bardziej ogólnym rozwiązaniem byłoby napisanie funkcji lub zestawu funkcji, które obsługują Exception dla znanych HRESULT i ponownie rzucają bardziej specyficzny wyjątek. Na przykład:

static void HandleKnownExceptions(Action f) 
{ 
    try 
    { 
     f(); 
    } 
    catch (Exception ex) 
    { 
     // Detect expected HRESULTs and throw the more-specific exception 
     // type for each. 
    } 
} 

Obie te metody działają równie dobrze w C++ i C#.

Należy pamiętać, że niekoniecznie musi to nastąpić, gdy Exception zostanie wyrzucony bezpośrednio przez platformę lub inne komponenty. W warstwie ABI środowiska wykonawczego systemu Windows nie ma wyjątków: wszystkie błędy są zgłaszane na granicy ABI przez HRESULT. CLR tłumaczy garść znanych HRESULT do bardziej specyficznych typów wyjątków, ale nie może wykonać ogólnego tłumaczenia.

+0

Dzięki James. Takie było moje podejście przy wychwytywaniu nieprawidłowego bufora HRESULT. Uważam, że to trochę dziwne, że programiści .NET muszą teraz radzić sobie z HRESULTS. Łatwo uzyskasz nieprawidłowy bufor podczas próby odszyfrowania nieprawidłowych danych, które mogły być hartowane lub zostały po prostu przycięte. Myślę, że prawie niemożliwe jest sprawdzenie zaszyfrowanych danych dla odpowiedniej długości, ponieważ zależy to od zastosowanego algorytmu i klucza. Już wystarczająco trudno jest znaleźć rozmiar użytego bloku.Złapanie nieprawidłowego błędu bufora jest kluczowe dla zapewnienia, że ​​nieprawidłowe dane są traktowane w sposób przyjazny dla użytkownika. –

+0

Ach, mój błąd. Źle zrozumiałem, jaki bufor był nieważny. Masz rację, obsługa tego rodzaju błędu to dobry pomysł :-) –

Powiązane problemy