在 C # 代码中,是否可以捕获从非托管库深处抛出的本机异常?如果是这样,你需要做什么不同的捕捉它或做一个标准的尝试... 捕捉它?
如果使用
try { } catch(Exception ex) { }
它将捕获所有异常,这取决于您如何调用外部库,您可能会得到一个 com 相关的异常,该异常封装了错误,但它将捕获错误。
C # 和本机代码之间的互操作层将异常转换为托管表单,允许 C # 代码捕获它。从现在开始。NET 2.0,catch (Exception)应该捕获任何不可恢复的错误。
catch (Exception)
一个标准的尝试接球应该可以做到这一点,我相信。
我遇到了类似的问题,System.data 异常抛出了一个 sqlClient 异常,但是没有捕获,因此添加了一个 try。.捕捉到我的代码在实例中起了作用
您可以使用 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); } } }
在使用.NET 反射器的某个地方,我看到了以下代码:
try { ... } catch(Exception e) { ... } catch { ... }
嗯,C # 不允许引发非系统派生的异常。异常类。据我所知,互操作封送拆收器捕获的任何异常都由继承 System 的异常类包装。例外。
所以我的问题是,是否有可能捕获一个不是 System.Exception 的异常。
Catch without ()将捕获包括本机异常在内的非 CLS 兼容异常。
try { } catch { }
有关更多信息,请参见下面的 FxCop 规则 Http://msdn.microsoft.com/en-gb/bb264489.aspx
这取决于您所说的本机异常的类型。如果您指的是 SEH 异常,那么 CLR 将执行以下两种操作之一。
这两者都将被一个简单的“ catch (Exception)”块捕获。
另一种可以跨越本机/托管边界的本机异常类型是 C + + 异常。我不确定它们是如何被映射/处理的。我的猜测是,由于 Windows 在 SEH 之上实现了 C + + 异常,因此它们只是以相同的方式映射。
差不多,但不完全是
try { ... } catch (Exception e) { ... }
但你还是会有潜在的问题。根据 MSDN,为了确保调用异常析构函数,您必须捕获以下内容:
try { ... } catch { ... }
这是确保调用异常析构函数的唯一方法(尽管我不确定为什么)。但是这样一来,你就只能在暴力和可能的内存泄漏之间进行权衡了。
顺便说一下,如果使用(Exception e)方法,您应该知道可能遇到的不同类型的异常。RuntimeWrappedException 是任何托管非异常类型将被映射到的类型(对于可以抛出字符串的语言) ,其他类型也将被映射,例如 OutOfMemorial yException 和 Access赋值 Exception。除了 E _ _ FAIL 之外的 COM 互操作 HResults 或异常将映射到 COMException,最后您将得到 E _ FAIL 或任何其他未映射异常的 SEHException。
那你该怎么办?最好的选择是不要从非托管代码中抛出异常!哈。实际上,如果您有一个选择,那么设置障碍并失败,使得选择哪个更糟糕,在异常处理期间有可能出现内存泄漏,或者不知道异常的类型。
和。Net Framework 4.8 如果本机代码中的异常是 处理得很好,然后您可以使用标准 try catch 捕获它。
try { //call native code method } catch (Exception ex) { //do stuff }
然而 ,如果本机代码位于您无法控制的第三方 dll 中,您可能会发现开发人员无意中抛出了未处理的异常。我发现除了一个全局错误处理程序之外,没有任何东西可以捕捉到这些错误。
private static void Main() { AppDomain.CurrentDomain.UnhandledException += OnUnhandledException; try { //call native code method } catch (Exception ex) { //unhandled exception from native code WILL NOT BE CAUGHT HERE } } private static void OnUnhandledException(object sender, UnhandledExceptionEventArgs e) { var exception = e.ExceptionObject as Exception; //do stuff }
这是有原因的。未处理的本机异常可能指示无法恢复的损坏状态(例如堆栈溢出或访问冲突)。但是,有些情况下,您仍然希望在终止进程之前执行一些操作,比如记录刚刚试图使您的 Windows 服务崩溃的错误! ! !
不再需要下列任何一项。 从.Net 2.0-3.5,你可以使用一个空的 catch:
try { //call native code method } catch (Exception ex) { //do stuff } catch { //do same stuff but without any exception detail }
从。Net 4它们启用了默认情况下的 关机了本机异常,并且您需要通过使用属性装饰您的方法来显式地重新打开它。
[HandleProcessCorruptedStateExceptions] [SecurityCritical] private static void Main() { try { //call native code method } catch (Exception ex) { //do stuff } }
还需要 app.config 文件的 改变:
<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true" /> </runtime> </configuration>