Können Sie in C # -Code eine native Ausnahme abfangen, die tief in einer nicht verwalteten Bibliothek ausgelöst wurde? Wenn ja, müssen Sie etwas anders machen, um es zu fangen, oder versucht ein Standard ... fangen, es zu bekommen?
Antworten:
Sie können Win32Exception verwenden und die NativeErrorCode-Eigenschaft verwenden, um sie entsprechend zu behandeln.
// http://support.microsoft.com/kb/186550
const int ERROR_FILE_NOT_FOUND = 2;
const int ERROR_ACCESS_DENIED = 5;
const int ERROR_NO_APP_ASSOCIATED = 1155;
void OpenFile(string filePath)
{
Process process = new Process();
try
{
// Calls native application registered for the file type
// This may throw native exception
process.StartInfo.FileName = filePath;
process.StartInfo.Verb = "Open";
process.StartInfo.CreateNoWindow = true;
process.Start();
}
catch (Win32Exception e)
{
if (e.NativeErrorCode == ERROR_FILE_NOT_FOUND ||
e.NativeErrorCode == ERROR_ACCESS_DENIED ||
e.NativeErrorCode == ERROR_NO_APP_ASSOCIATED)
{
MessageBox.Show(this, e.Message, "Error",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
}
}
Catch without () fängt nicht CLS-konforme Ausnahmen ab, einschließlich nativer Ausnahmen.
try
{
}
catch
{
}
Weitere Informationen finden Sie in der folgenden FxCop-Regel: http://msdn.microsoft.com/en-gb/bb264489.aspx
Die Interop-Ebene zwischen C # und nativem Code konvertiert die Ausnahme in eine verwaltete Form, sodass sie von Ihrem C # -Code abgefangen werden kann. Ab .NET 2.0 catch (Exception)
sollte alles andere als ein nicht behebbarer Fehler abgefangen werden.
Irgendwo mit einem .NET-Reflektor habe ich den folgenden Code gesehen:
try {
...
} catch(Exception e) {
...
} catch {
...
}
Hmm, C # erlaubt es nicht, eine Ausnahme auszulösen, die nicht von der System.Exception-Klasse abgeleitet ist. Und soweit ich weiß, wird jede vom Interop-Marshaller vorsichtige Ausnahme von der Ausnahmeklasse umschlossen, die die System.Exception erbt.
Meine Frage ist also, ob es möglich ist, eine Ausnahme abzufangen, die keine System.Exception ist.
Dies hängt davon ab, um welche Art von nativer Ausnahme es sich handelt. Wenn Sie sich auf eine SEH-Ausnahme beziehen, führt die CLR eines von zwei Dingen aus.
Beide werden mit einem einfachen "catch (Exception)" - Block abgefangen.
Die andere Art von nativer Ausnahme, die die native / verwaltete Grenze überschreiten kann, sind C ++ - Ausnahmen. Ich bin nicht sicher, wie sie zugeordnet / behandelt werden. Ich vermute, da Windows C ++ - Ausnahmen zusätzlich zu SEH implementiert, werden sie auf die gleiche Weise zugeordnet.
Windows implements C++ exceptions on top of SEH
- Dies scheint nur für VC zu gelten?
Fast, aber nicht ganz. Sie werden die Ausnahme mit abfangen
try
{
...
}
catch (Exception e)
{
...
}
Sie werden jedoch immer noch potenzielle Probleme haben. Laut MSDN müssten Sie Folgendes abfangen, um sicherzustellen, dass Ausnahmezerstörer aufgerufen werden:
try
{
...
}
catch
{
...
}
Dies ist die einzige Möglichkeit, um sicherzustellen, dass ein Ausnahmezerstörer aufgerufen wird (obwohl ich nicht sicher bin, warum). Damit haben Sie jedoch den Kompromiss zwischen Brute Force und einem möglichen Speicherverlust.
Wenn Sie den Ansatz (Ausnahme e) verwenden, sollten Sie übrigens die verschiedenen Arten von Ausnahmen kennen, auf die Sie möglicherweise stoßen. Mit RuntimeWrappedException wird jeder verwaltete Nicht-Ausnahmetyp zugeordnet (für Sprachen, die eine Zeichenfolge auslösen können), und andere werden zugeordnet, z. B. OutOfMemoryException und AccessViolationException. COM Interop HRESULTS oder andere Ausnahmen als E___FAIL werden COMException zugeordnet, und schließlich haben Sie am Ende SEHException für E_FAIL oder eine andere nicht zugeordnete Ausnahme.
Was solltest du also tun? Die beste Wahl ist, keine Ausnahmen von Ihrem nicht verwalteten Code zu werfen! Hah. Wirklich, wenn Sie eine Wahl haben, stellen Sie Barrieren auf und scheitern Sie, wodurch die Wahl schlechter wird, die Möglichkeit eines Speicherverlusts während der Ausnahmebehandlung besteht oder Sie nicht wissen, um welchen Typ es sich bei Ihrer Ausnahme handelt.
Wenn Sie eine verwenden
try
{
}
catch(Exception ex)
{
}
Je nachdem, wie Sie die externen Bibliotheken aufrufen, werden ALLE Ausnahmen abgefangen. Möglicherweise wird eine com-bezogene Ausnahme angezeigt, die den Fehler kapselt, den Fehler jedoch abfängt.