tags:

views:

4858

answers:

8

In C# code can you catch a native exception thrown from deep in some unmanaged library? If so do you need to do anything differently to catch it or does a standard try...catch get it?

+9  A: 

If you use a

try
{

}
catch(Exception ex)
{

}

it will catch ALL exceptions, depending on how you call the external libraries you might get a com related exception that encapsulates the error but it will catch the error.

Mitchel Sellers
You can't catch a StackOverflow or OutOfMemoryException though, no matter what, correct?
Chris
those are ending errors, that halt the application, so yes you cannot work with them.
Mitchel Sellers
+6  A: 

The interop layer between C# and native code will convert the exception into a managed form, allowing it to be caught by your C# code. As of .NET 2.0, catch (Exception) should catch anything other than a nonrecoverable error.

Curt Hagenlocher
In .NET 1.x, it's possible for an exception to be thrown that doesn't derive from the Exception class, but this ability is turned off by default in 2.0
Curt Hagenlocher
@Curt really? What was it for?
Camilo Martin
I don't actually know.
Curt Hagenlocher
A: 

A standard try catch should do the trick i believe.

I run into a similar problem with a System.data exception throwing a sqlClient exception which was uncaught, adding a try..catch into my code did the trick in the instance

Dean
+8  A: 

You can use Win32Exception and use its NativeErrorCode property to handle it appropriately.

// 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);
     }
    }
}
Vivek
I believe this isn't automatic, but only thrown when you use a P/Invoke signature that specifies it. And it's thrown based on a Win32 error code, not a Win32 exception.
Curt Hagenlocher
+2  A: 

Somewhere using a .NET Reflector I've seen the following code:

try {
  ...
} catch(Exception e) {
  ...
} catch {
  ...
}

Hmm, C# does not allow to throw an exception not deriving from the System.Exception class. And as far as I known any exception cautch by the interop marshaller is wrapped by the exception class that inherits the System.Exception.

So my question is whether it's possible to catch an exception that is not a System.Exception.

Michael Damatov
It is possible to emit or otherwise create IL that throws an arbitrary object. The C# compiler won't let you do it, but other compilers may, or like I said you can directly emit the IL. A catch statement with no type will catch arbitrary objects as well as objects inheriting Exception.
technophile
+3  A: 

Catch without () will catch non-CLS compliant exceptions including native exceptions.

try
{

}
catch
{

}

See the following FxCop rule for more info http://msdn.microsoft.com/en-gb/bb264489.aspx

trampster
+1  A: 

This depends on what type of native exception you are talking about. If you're referring to an SEH exception then the CLR will do one of two things.

  1. In the case of a known SEH error code it will map it to the appropriate .Net exception (i.e. OutOfMemoryException)
  2. In the case of an un-mappable (E_FAIL) or unknown code it will just throw an SEHException instance.

Both of these will be caught with a simple "catch (Exception)" block.

The other type of native exception which can cross the native managed boundary are C++ exceptions. I'm not sure how they are mapped/handled. My guess is that since Windows implements C++ exceptions on top of SEH, they are just mapped the same way.

JaredPar
A: 

Almost, but not quite. You will catch the exception with

try 
{
  ...
}
catch (Exception e)
{
  ...
}

but you will still have potential problems. According to MSDN, in order to insure exception destructors are called you would have to catch like:

try
{
  ...
}
catch
{
  ...
}

This is the only way to insure an exception destructor is called (though I'm not sure why). But that leaves you with the tradeoff of brute force versus a possible memory leak.

Incidentally, if you use the (Exception e) approach you should know the different types of exceptions you might come across. RuntimeWrappedException is what any managed non-exception type will be mapped to (for languages that can throw a string), and others will be mapped, such as OutOfMemoryException and AccessViolationException. COM Interop HRESULTS or exceptions other than E___FAIL will map to COMException, and finally at the end you have SEHException for E_FAIL or any other unmapped exception.

So what should you do? Best choice is don't throw exceptions from your unamanaged code! Hah. Really though if you have a choice, put up barriers and failing that make the choice of which is worse, a chance of a memory leak during exception handling, or not knowing what type your exception is.

nedruod