在 C# 代码中,您能否捕获来自某个非托管库深处抛出的本地异常?如果可以,那么是否需要采取不同的方式来捕获它,或者标准的 try...catch 可以捕获它?
您可以使用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 会捕获非CLS兼容异常,包括本地异常。
try
{
}
catch
{
}
请参阅以下 FxCop 规则以获取更多信息: http://msdn.microsoft.com/en-gb/bb264489.aspx
在C#和本地代码之间的Interop层将异常转化为托管形式,从而使其可以被你的C#代码捕获。从.NET 2.0开始,catch (Exception)
应该可以捕获除不可恢复错误以外的任何异常。
我在某处使用 .NET Reflector 看到了下面的代码:
try {
...
} catch(Exception e) {
...
} catch {
...
}
哦,C# 不允许抛出一个不继承自 System.Exception 类的异常。而且据我所知,任何由交互操作封送程序捕获的异常都会被继承自 System.Exception 的异常类包装。
那么我的问题是是否有可能捕获一个不是 System.Exception 的异常。
使用 .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>
try
{
...
}
catch (Exception e)
{
...
}
但是你仍然可能会遇到潜在的问题。根据MSDN,为了确保异常析构函数被调用,你需要像这样catch异常:
try
{
...
}
catch
{
...
}
我相信一个标准的try catch应该可以解决问题。
我曾经遇到过类似的问题,当时System.data异常抛出了一个未被捕获的sqlClient异常,在我的代码中添加了try..catch后,问题得到了解决。
如果您使用了
try
{
}
catch(Exception ex)
{
}
它将捕获所有异常,取决于您如何调用外部库,您可能会得到一个封装错误的 com 相关异常,但是它将捕获该错误。
Exception
类的子类异常,但你可以使用catch(...){}
来捕获其他异常,不是吗? - will