2012-09-25 5 views
6

Wenn ein Windows-Laufzeittyp einen COM-Fehler auslöst, scheint .NET diesen Fehler oft (oder immer?) Nur in eine Exception-Instanz einzubetten. Die Fehlermeldung enthält den COM HRESULT-Fehlercode. Bei Verwendung der neuen Cryptographic API mit AES-CBC zum Beispiel führt eine falsche Pufferlänge zu einem Exception mit der Meldung "Der angegebene Benutzerpuffer ist für die angeforderte Operation nicht gültig. (Exception from HRESULT: 0x800706F8)".Wie behandelt man WinRT-Exceptions, die zu Exception führen?

Nun, wie sollen wir mit diesen Ausnahmen umgehen? Sollten wir den HRESULT Code von der Ausnahme lesen, um eine Idee zu bekommen, welche Art von Ausnahme das war? In klassischen .NET würde ich eine CryptographicException bekommen, die ich verwenden könnte, um kryptografische Fehler von anderen Fehlern zu unterscheiden.

Eine andere Sache, die ich nicht verstehe, ist, dass die Microsoft-Codequalitätsregeln angeben, dass man niemals Exception sondern immer abgeleitete Typen werfen sollte. Der Grund ist, dass niemand gezwungen sein sollte, den allgemeinen Exception zu fangen, der auch mehr fatale Ausnahmen wie OutOfMemoryException fängt. Eine andere Regel besagt, dass man niemals Exceptio n in Bibliotheken fangen sollte. Wie können wir diesen Richtlinien folgen, wenn wir gezwungen sind, Exception in Windows Store-Apps oder WinRT-Bibliotheken zu erfassen?

Übrigens: Clemens Vasters shows in his blog how we can catch Exception while avoiding to catch fatal exception. Ich nehme an, Exception ist nicht mehr schlechter Code dann.

+0

In Bezug auf den verknüpften Blog-Eintrag können viele der aufgeführten "fatalen" Ausnahmen nicht vom verwalteten Code abgefangen werden. Insbesondere "StackOverflowException", obwohl ich mir ziemlich sicher bin, dass auch AVs nicht abgefangen werden können (beide können natürlich im nativen Code abgefangen werden, aber das ist gefährlich). Beachten Sie auch, dass einige Ausnahmen, die _fall_ fatal sind, tatsächlich nicht so sind. Zum Beispiel geben viele COM-Komponenten "E_OUTOFMEMORY" zurück, wenn der Speicherplatz in einem bestimmten Puffer erschöpft ist. Dieses HRESULT wird als OutOfMemoryException übersetzt, bedeutet jedoch nicht, dass der gesamte Adressraum des Prozesses erschöpft ist. –

Antwort

4

Es ist möglich, Exception abzufangen, bestimmte Fehler zu behandeln, indem das HRESULT eingeschaltet wird, und Exception erneut zu werfen, wenn der Fehler "unerwartet" war. Zum Beispiel

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

(Ich möchte darauf hinweisen, dass ein ungültigen Puffer klingt eher wie ein logischen Fehler als ein Laufzeitfehler, so frage ich mich, ob diese besondere Ausnahme wirklich gefangen werden soll.)

Alternativ kann einen Eine allgemeinere Lösung wäre, eine Funktion oder einen Satz von Funktionen zu schreiben, die Exception für bekannte HRESULTs behandeln und eine spezifischere Ausnahme erneut auslösen. Zum Beispiel

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

Beide Ansätze funktionieren gleichermaßen in C++ und C#.

Beachten Sie, dass es nicht unbedingt der Fall ist, dass Exception direkt von der Plattform oder anderen Komponenten geworfen wird. Auf der ABI-Schicht von Windows Runtime gibt es keine Ausnahmen: Alle Fehler werden über die ABI-Grenze von HRESULT gemeldet. Die CLR übersetzt eine Handvoll bekannter HRESULT in spezifischere Ausnahmetypen, kann jedoch keine allgemeine Übersetzung durchführen.

+0

Danke James. Das war mein Ansatz, wenn ich den ungültigen Puffer HRESULT abfing. Ich finde es etwas merkwürdig, dass .NET-Programmierer jetzt mit HRESULTS umgehen müssen. Sie erhalten leicht einen ungültigen Puffer, wenn Sie versuchen, ungültige Daten zu entschlüsseln, die mit oder einfach beschnitten wurden. Ich denke, dass es nahezu unmöglich ist, verschlüsselte Daten auf die richtige Länge zu prüfen, da dies vom verwendeten Algorithmus und Schlüssel abhängt. Es ist schon schwer genug, um die verwendete Blockgröße herauszufinden.Das Abfangen des ungültigen Pufferfehlers ist wichtig, um sicherzustellen, dass ungültige Daten benutzerfreundlich behandelt werden. –

+0

Ah, mein Fehler dann. Ich habe missverstanden, welcher Puffer ungültig war. Du hast Recht, mit dieser Art von Fehlern umzugehen ist eine gute Idee :-) –

Verwandte Themen