2009-09-15 15 views
24

Mam nadzieję, że ktoś może mi pomóc. Mam wyjątek od COM, który muszę złapać, a następnie spróbować zrobić coś innego, wszystkie inne powinny zostać zignorowane. Mój komunikat błędu z wyjątkiem jest:Catching specyficzny kod błędu COMException

System.Runtime.InteropServices.COMException (0x800A03EC): Microsoft Office Excel nie może uzyskać dostępu do pliku 'C: \ Test.xls'. Istnieje kilka możliwych powodów:

Więc moja pierwsza próba została

try 
{ 
// something 
} 
catch (COMException ce) 
{ 
    if (ce.ErrorCode == 0x800A03EC) 
    { 
     // try something else 
    } 
} 

Jednak potem przeczytałem ostrzeżenie kompilatora:

Warning 22 porównaniu do integralnego stałej jest bezużyteczna; stała jest poza zasięgiem typu 'int' ..... ExcelReader.cs 629 21

Teraz wiem, że 0x800A03EC jest hresult a ja po prostu wyglądał na MSDN i przeczytać:

HRESULT jest 32-bitowa wartość, podzielona na trzy pola: a kod ciężkości, kodu obiektu, a kod błędu. Kod o zagrożeniu wskazuje, czy zwracana wartość reprezentuje błąd informacji, ostrzeżenia lub . Kod obiektu określa obszar systemu odpowiedzialnego za błąd.

Tak więc moim ostatecznym pytaniem jest, w jaki sposób mogę upewnić się, że pułapkę tego wyjątku? Lub w jaki sposób uzyskać kod błędu z HResult?

Z góry dziękuję.

+0

Wystarczy, aby dodać notatkę. Nie jest łatwo odtworzyć ten wyjątek, ponieważ potrzebuję do tego konkretnej konfiguracji, do której zmierzam, ale myślę, że zapytanie tutaj może być szybsze :) – Ian

Odpowiedz

36

Kod błędu powinien być liczbą całkowitą bez znaku; można wykonać porównanie następująco:

try { 
    // something 
} catch (COMException ce) { 
    if ((uint)ce.ErrorCode == 0x800A03EC) { 
     // try something else 
    } 
} 
+0

tak, z kodu C#, nie ma sposobu, aby coś zrobić, '' przy użyciu WinErrorsOrWhatever', a następnie 'if ((uint) ce.ErrorCode == E_UNEXPECTED_OR_WHATEVER)'? – rturrado

+15

Powyższe działa, ale tylko po skompilowaniu w kontekście niezaznaczonym. W przeciwnym razie ujemny kod 'ce.ErrorCode' nie będzie konwertować szczęśliwie na pozytywny' uint'. W rzeczy samej przyjemniej jest przekonwertować drugą stronę symbolu '==' i powiedzieć 'if (ce.ErrorCode == unchecked ((int) 0x800A03EC)) {...}'. Zobacz [przykład na MSDN] (http://msdn.microsoft.com/en-us/library/system.exception.hresult.aspx). –

+0

Czy to jest błąd ramowy? Czy wyjątek.Jak należy zdefiniować jako uint? – Tristan

0

I rzeczywiście udało się to uruchomiony w systemie, co potrzebne i okazało się, że kod błędu był -2146807284.

Patrząc na to, jeśli skonwertuję 0x800A03EC na Binary, traktuję to jako komplement 2, to można obliczyć wartość.

+3

Tak, alternatywą jest konwersja HRESULT na liczbę całkowitą ze znakiem, ale może pozostawienie kodu szesnastkowego powoduje, że jest on bardziej czytelny (i łatwiejszy do google). –

10

Wartość HRESULT ma 32 bity podzielone na trzy pola: kod istotności, kod obiektu i kod błędu. Kod istotności wskazuje, czy zwracana wartość reprezentuje informacje, ostrzeżenie lub błąd. Kod obiektu o numerze identyfikacyjnym określa obszar systemu odpowiedzialnego za błąd. Kod błędu jest unikalnym numerem, który jest przypisany do reprezentowania wyjątku. Każdy wyjątek jest odwzorowany na odrębną HRESULT. Fragment: http://en.wikipedia.org/wiki/HRESULT

Z czego wnoszę, pierwsza połowa bitów hresult może zmieniać się w zależności od systemu/procesu, który wywołuje wyjątek. Druga połowa zawiera typ błędu.

Kod powinien wyglądać następująco:

try { 
    // something 
} catch (COMException ce) { 
    if ((uint)ce.ErrorCode & 0x0000FFFF == 0x800A03EC) { 
     // try something else 
    } 
} 

Uwaga: Należy pamiętać, że nie jestem facet .NET, więc być zmęczony błędów składniowych w powyższym kodzie.

+1

+1: Dziękujemy za szczegółowy podział. To coś od jakiegoś czasu, ale przydatne dla każdego, kto jest zainteresowany. – Ian

+7

Do czego służy '' 0x0000FFFF'? To "usunie" (ustawione na 0) lewą połowę uint, więc nigdy nie będzie "== 0x800A03EC", prawda? –