First of all, it's most likely that you don't need to catch exception write around every call to something unmanaged. You can catch part of the exceptions only at the point where you know how to handle some
specific
exceptions. I call such points
"competency points". All exceptions should be caught only somewhere on the top stack frame of each stack and in some special points, such as inside the main message/event loop of the UI application.
Having this in mind… the simplest case is so simple:
try {
someCodeInvolvingUnmanagedCode();
} catch (FirstSpecificExceptionType ex) {
HandleFirstSpecificExceptionType(ex);
} catch (SecondSpecificExceptionType ex) {
HandleSecondSpecificExceptionType(ex);
}
The unmanaged exception will be caught, too, it… you catch then or catch all exceptions (
catch(...)
). I usually recommend to catch all uncaught exceptions up the stack, as I mentioned above.
Now, please see my comment to the comment by Philippe Mori to the question. The problem is: in managed code, all exceptions will be caught in the form of some exception type derived from the common base class,
System::Exception
. In unmanaged code, it could be… anything. It's good it this is a system exception (integer division by zero, for example), it will be properly wrapped and delivered. What if the exception is the instance of some unmanaged C++ class? It will be caught, but you would not be able to access specific exception information. But you can catch them, too!
This is the power of mixed mode (managed + unmanaged) C++/CLI projects: you can combine managed and unmanaged code. In such cases, if you have to use some unmanaged exception classes defined somewhere, I would wrap them in some managed exception classes you could derive from
System::Exception
. How would
someCodeInvolvingUnmanagedCode
look like? It could be:
void someCodeInvolvingUnmanagedCode() {
try {
someUnmanagedCode();
} catch (FirstUnmanagedExceptionType ex) {
throw gcnew FirstSemanticManagedExceptionWrapper(ex);
} catch (SecondUnmanagedExceptionType ex) {
throw gcnew SecondSemanticManagedExceptionWrapper(ex);
} catch (std::exception) { throw gcnew StdExceptionWrapper(ex);
}
}
This way, you could have the point where you catch all exceptions as managed types derived from the
System::Exception
, even in one catch statement:
try {
} catch (System::Exception^ ex) {
someCommonHandler(ex);
}
But of course you can catch it in mixed way:
try {
someMixOfManagedUnmanagedCode();
}
catch (std::exception& ex) {
}
catch (System::Exception^ ex) {
}
And so on…
—SA