2012-09-25 19 views
6

Se un tipo di runtime di Windows genera un errore COM, .NET sembra capovolgere spesso questo errore (o sempre?) Solo in un'istanza Exception. Il messaggio di errore include il codice di errore HR HRESULT. Ad esempio, quando si utilizza la nuova API Cryptographic con AES-CBC, una lunghezza del buffer errata risulta in un Exception con il messaggio "Il buffer utente fornito non è valido per l'operazione richiesta. (Exception from HRESULT: 0x800706F8)".Come gestire le eccezioni WinRT che risultano in Eccezione?

Bene, come possiamo gestire queste eccezioni? Dovremmo leggere il codice HRESULT dall'eccezione per avere un'idea del tipo di eccezione che era? Nel classico .NET avrei un CryptographicException che potrei usare per distinguere gli errori di crittografia da altri errori.

Un'altra cosa che non capisco è che le regole di qualità del codice Microsoft affermano che non si dovrebbero mai lanciare eccezioni ma sempre tipi derivati. Il motivo è che nessuno dovrebbe essere costretto a prendere il generale Exception che rileva eccezioni più fatali come OutOfMemoryException. Un'altra regola dice che non si dovrebbe mai, mai catturare Exceptio n nelle biblioteche. Come possiamo seguire queste politiche se siamo costretti a catturare Exception nelle app di Windows Store o nelle librerie WinRT?

A proposito: Clemens Vasters shows in his blog how we can catch Exception while avoiding to catch fatal exception. Presumo che catturare Exception non è più codice cattivo allora.

+0

Per quanto riguarda il post di blog collegato, molte delle eccezioni "fatali" elencate non possono essere rilevate dal codice gestito. In particolare, 'StackOverflowException', anche se sono abbastanza sicuro che non sia possibile catturare anche AV (entrambi possono essere catturati nel codice nativo, ovviamente, ma farlo è pericoloso). Si noti inoltre che alcune eccezioni che _appear_ fatal potrebbero non essere effettivamente così. Ad esempio, molti componenti COM restituiscono 'E_OUTOFMEMORY' quando lo spazio in un determinato buffer viene esaurito. Questo HRESULT sarà tradotto come OutOfMemoryException, ma ciò non significa che il processo abbia esaurito l'intero spazio degli indirizzi. –

risposta

4

È possibile catturare Exception, gestire errori particolari accendendo l'HRESULT e rilanciare lo Exception se l'errore era "imprevisto". Ad esempio,

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

(ricordo che fornisce un buffer non valida suona più come un errore logico che un errore di runtime, quindi mi chiedo se questo particolare eccezione in realtà dovrebbe essere catturato.)

In alternativa, un soluzione più generale sarebbe scrivere una funzione o una serie di funzioni che gestiscono Exception per HRESULT noti e rigenera un'eccezione più specifica. Ad esempio,

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

Entrambi questi approcci funzionano ugualmente bene sia in C++ e C#.

Si noti che non è necessariamente il caso che Exception venga generato direttamente dalla piattaforma o da altri componenti. Al livello ABI di Windows Runtime, non ci sono eccezioni: tutti gli errori vengono segnalati attraverso il limite ABI da HRESULT. Il CLR traduce una manciata di HRESULT noti in tipi di eccezioni più specifici, ma non può eseguire una traduzione generale.

+0

Grazie James. Questo è stato il mio approccio quando ho catturato il buffer non valido HRESULT. Trovo un po 'strano che i programmatori .NET ora debbano occuparsi di HRESULTS. È possibile ottenere facilmente un buffer non valido durante il tentativo di decrittografare i dati non validi che potrebbero essere stati mitigati o semplicemente ritagliati. Penso che sia quasi impossibile controllare i dati crittografati per la giusta lunghezza perché questo dipende dall'algoritmo e dalla chiave usati. È già abbastanza difficile scoprire la dimensione del blocco utilizzato.Acquisire l'errore del buffer non valido è fondamentale per garantire che i dati non validi siano trattati in modo user friendly. –

+0

Ah, errore mio allora. Ho frainteso quale buffer non era valido. Hai ragione, gestire questo tipo di errore è una buona idea :-) –

Problemi correlati