你能捕捉到C#代码中的本机exception吗?

在C#代码中,你能捕捉到一些非托pipe库深处抛出的本地exception吗? 如果是这样,你需要做不同的事情来抓住它,或做一个标准的尝试…赶上得到它?

您可以使用Win32Exception并使用其NativeErrorCode属性来适当地处理它。

// 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()将捕获非CLS兼容的exception,包括本地exception。

 try { } catch { } 

有关更多信息,请参阅以下FxCop规则http://msdn.microsoft.com/zh-cn/bb264489.aspx

C#和本地代码之间的互操作层将exception转换为托pipeforms,允许它被C#代码捕获。 从.NET 2.0开始, catch (Exception)应该捕获除了不可恢复的错误之外的任何东西。

某处使用.NET Reflector我已经看到下面的代码:

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

嗯,C#不允许抛出一个不是从System.Exception类派生的exception。 就我所知,任何由interop编组的exceptioncautch被inheritance了System.Exception的exception类所包装。

所以我的问题是是否有可能捕获不是System.Exception的exception。

这取决于你在说什么types的本机exception。 如果你指的是SEHexception,那么CLR将做两件事情之一。

  1. 在已知SEH错误代码的情况下,它会将其映射到适当的.Netexception(即OutOfMemoryException)
  2. 在不可映射(E_FAIL)或未知代码的情况下,它只会抛出一个SEHException实例。

这两个都将被捕获一个简单的“catch(Exception)”块。

可以跨越本机/pipe理边界的另一种本地exception是C ++exception。 我不知道他们如何被映射/处理。 我的猜测是,由于Windows在SEH之上实现了C ++exception,因此它们只是以相同的方式映射。

几乎,但不完全。 你会发现exception

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

但是你仍然有潜在的问题。 根据MSDN ,为了确保exception析构函数被调用,你必须像这样:

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

这是确保调用exception析构函数的唯一方法(尽pipe我不知道为什么)。 但是这会让你面对蛮力和可能的内存泄漏的折衷。

顺便说一下,如果使用(Exception e)方法,您应该知道可能遇到的不同types的exception。 RuntimeWrappedException是任何托pipe的非exceptiontypes将被映射到(对于可以引发string的语言),其他将被映射,如OutOfMemoryException和AccessViolationException。 COM Interop HRESULTS或E___FAIL以外的exception将映射到COMException,最后在E_FAIL或其他任何未映射的exception中最后出现SEHException。

那么你应该怎么做? 最好的select是不要抛出未经pipe理的代码的exception! 哈。 实际上,如果你有select的话,就提出一些障碍,如果不能做出更糟糕的select,在exception处理过程中出现内存泄漏的机会,或者不知道你的exception是什么types。

如果你使用一个

 try { } catch(Exception ex) { } 

它会捕获所有的exception,这取决于你如何调用外部库,你可能会得到一个com封装错误的com相关的exception,但它会捕获错误。

一个标准的尝试抓住应该做我相信的诡计。

我碰到了一个类似的问题,引发了一个System.Dataexception抛出一个sqlClientexception,这是一个未被捕获的,添加一个try..catch到我的代码中的伎俩在实例中