在C#代码中,您是否可以捕获从某些非托管库中深入抛出的本机异常?如果是这样,你需要做任何不同的事情才能抓住它或做一个标准的尝试......抓住它吗?
答案 0 :(得分:31)
您可以使用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);
}
}
}
答案 1 :(得分:16)
Catch without()将捕获非CLS兼容的异常,包括本机异常。
try
{
}
catch
{
}
有关详细信息,请参阅以下FxCop规则 http://msdn.microsoft.com/en-gb/bb264489.aspx
答案 2 :(得分:11)
C#和本机代码之间的互操作层将异常转换为托管表单,允许它被C#代码捕获。从.NET 2.0开始,catch (Exception)
应该捕获除了不可恢复的错误以外的任何内容。
答案 3 :(得分:5)
使用.NET Reflector的地方我看过以下代码:
try {
...
} catch(Exception e) {
...
} catch {
...
}
嗯,C#不允许抛出异常而不是从System.Exception类派生。据我所知,interop marshaller的任何异常包都由继承System.Exception的异常类包装。
所以我的问题是是否可以捕获不是System.Exception的异常。
答案 4 :(得分:5)
这取决于您所谈论的本机异常类型。如果你指的是SEH例外,那么CLR会做两件事之一。
这两个都将被一个简单的“catch(Exception)”块捕获。
可以跨越本机/托管边界的其他类型的本机异常是C ++异常。我不确定它们是如何映射/处理的。我的猜测是,由于Windows在SEH之上实现了C ++异常,因此它们只是以相同的方式映射。
答案 5 :(得分:3)
几乎,但不完全。您将使用
捕获异常try
{
...
}
catch (Exception e)
{
...
}
但你仍然有潜在的问题。根据{{3}},为了确保调用异常析构函数,你必须注意:
try
{
...
}
catch
{
...
}
这是确保调用异常析构函数的唯一方法(虽然我不确定为什么)。但是,这会让你对蛮力与可能的内存泄漏进行权衡。
顺便说一句,如果您使用(例外e)方法,您应该知道可能遇到的不同类型的例外。 RuntimeWrappedException是任何托管的非异常类型将被映射到的(对于可以抛出字符串的语言),而其他类型将被映射,例如OutOfMemoryException和AccessViolationException。 COM Interop HRESULTS或E___FAIL以外的异常将映射到COMException,最后在E_FAIL或任何其他未映射的异常的最后都有SEHException。
那你该怎么办?最好的选择是不要从你的非托管代码中抛出异常!哈。实际上,如果你有一个选择,设置障碍和失败使得选择哪个更糟,在异常处理期间内存泄漏的可能性,或者不知道你的异常是什么类型。
答案 6 :(得分:0)
如果您使用
try
{
}
catch(Exception ex)
{
}
它将捕获所有异常,具体取决于您如何调用外部库,您可能会获得一个封装错误的com相关异常,但它会捕获错误。
答案 7 :(得分:0)
标准尝试捕获应该做我相信的技巧。
我遇到一个类似的问题,一个System.data异常抛出一个未被捕获的sqlClient异常,在我的代码中添加了一个try..catch,在实例中做了诀窍