2013-12-16 15 views
5

Utilizzo una DLL non gestita con una funzione che genera std::exception.Eccezione di dll non gestita in .NET

Utilizzo un wrapper .NET DLL in modo che possa essere distribuito per l'utilizzo nei programmi .NET.

Mi piacerebbe essere in grado cattura il messaggio dell'eccezione nativo, ma tutto quello che sto ricevendo è System.Runtime.InteropServices.SEHException("External component has thrown an exception.")

Esiste un modo per propagare i dettagli di eccezione? Forse dovrei esportare un'eccezione personalizzata dalla DLL nativa? Come lo farei?

Grazie

DLL nativa:

__declspec(dllexport) void __stdcall W32DLLFunc(int param) { 
    if (param < 0) { 
    throw new exception("Error: param must be > 0"); 
    } 
    ... 
} 

.net DLL:

[DllImport("nw32.dll", CharSet = CharSet::Auto)] 
static void W32DLLFunc(int param); 

programma vb.net:

Try 
    W32DLLFunc(-1) 
Catch ex As Exception 
    MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) 
End Try 

risposta

2

C++ nativo eccezioni sono nativi eccezioni C++. Non funzionano con cose che non sono C++. Non funzionano nemmeno tra diverse versioni di C++.

Le eccezioni Native C++ non sono adatte all'interoperabilità.

Il meccanismo standard per la restituzione informazioni di errore di DLL è per restituire un valore per indicare successo o il fallimento e di utilizzare SetLastError e GetLastError comunicare un codice di errore se la funzione non è riuscita.

Se si desidera un meccanismo standard per restituire più informazioni di un codice di errore, è necessario consultare COM, che ha IErrorInfo.

Ma sarebbe più semplice definire alcuni codici di errore.

Se possibile, modificherei la DLL originale in modo che non vi siano perdite di eccezioni. Se ciò è impossibile perché i client C++ esistenti dipendono dal progetto corrente, aggiungerei un'API parallela: una nuova versione di ogni funzione esportata che chiama l'originale, cattura le eccezioni e restituisce i codici di errore. Questo è tutto il boilerplate che può essere nascosto nei macro. Se non riesci a toccare la DLL, aggiungerei un wrapper nativo per tradurre le eccezioni.

Aggiornamento

Come suggerito da IInspectable, un'altra opzione è quella di creare un assembly in modalità mista.

Aggiungi una classe .Net alla libreria C++ esistente. Ciò dovrebbe fornire un wrapper per ogni funzione API che richiama l'API originale, rileva qualsiasi eccezione, copia i dettagli in un'eccezione .Net e genera l'eccezione .Net.

Mantenendo tutta la gestione delle eccezioni native all'interno della DLL, si evitano i problemi con le eccezioni C++ che attraversano i confini della DLL. Le eccezioni avvolte possono essere consumate in qualsiasi linguaggio .Net senza la necessità di creare dichiarazioni per le funzioni esportate. L'unico svantaggio è che è necessaria un'API aggiuntiva per l'interoperabilità con un altro codice nativo.

+0

È vero, la famosa eccezione "E msc'. Cancellerò i miei commenti in cambio di un upvote.È ancora possibile aggiungere una nota sulla scrittura di un wrapper C++/CLI per tradurre eccezioni C++ in eccezioni .NET, che sembra essere la soluzione più pulita. L'assembly in modalità mista può essere utilizzato anche dal codice nativo e gestito. – IInspectable

+0

Cheers. Mi era venuto in mente un wrapper C++/CLI, ma non sapevo a priori in che modo le eccezioni native interagissero con C++/CLR. [Questo articolo] (http://msdn.microsoft.com/en-us/library/df24ysb6.aspx) implica quasi che funzioni, quindi ho provato e funziona. Ho aggiornato la mia risposta. – arx

Problemi correlati