您能在 C# 代码中捕获本机异常吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/150544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can you catch a native exception in C# code?
提问by Matt
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?
在 C# 代码中,您能否捕获从某个非托管库深处抛出的本机异常?如果是这样,您需要做任何不同的事情来捕获它还是标准的 try...catch get ?
采纳答案by Vivek
You can use Win32Exceptionand use its NativeErrorCode property to handle it appropriately.
您可以使用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);
}
}
}
回答by Mitchel Sellers
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.
它将捕获所有异常,具体取决于您调用外部库的方式,您可能会得到一个封装错误的与 com 相关的异常,但它会捕获错误。
回答by Curt Hagenlocher
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.
C# 和本机代码之间的互操作层会将异常转换为托管形式,允许您的 C# 代码捕获它。从 .NET 2.0 开始,catch (Exception)
应该捕获除不可恢复错误之外的任何内容。
回答by Dean
A standard try catch should do the trick i believe.
我相信标准的 try catch 应该可以解决问题。
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
我遇到了一个类似的问题,System.data 异常抛出了一个未捕获的 sqlClient 异常,在我的代码中添加一个 try..catch 在实例中起到了作用
回答by Michael Damatov
Somewhere using a .NET Reflector I've seen the following code:
在某处使用 .NET Reflector 我看到了以下代码:
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.
嗯,C# 不允许抛出不是从 System.Exception 类派生的异常。据我所知,interop marshaller 的任何异常 cautch 都由继承 System.Exception 的异常类包装。
So my question is whether it's possible to catch an exception that is not a System.Exception.
所以我的问题是是否有可能捕获不是 System.Exception 的异常。
回答by trampster
Catch without () will catch non-CLS compliant exceptions including native exceptions.
Catch without () 将捕获不符合 CLS 的异常,包括本机异常。
try
{
}
catch
{
}
See the following FxCop rule for more info http://msdn.microsoft.com/en-gb/bb264489.aspx
有关详细信息,请参阅以下 FxCop 规则 http://msdn.microsoft.com/en-gb/bb264489.aspx
回答by JaredPar
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.
这取决于您所谈论的本机异常类型。如果您指的是 SEH 异常,则 CLR 将执行以下两项操作之一。
- In the case of a known SEH error code it will map it to the appropriate .Net exception (i.e. OutOfMemoryException)
- In the case of an un-mappable (E_FAIL) or unknown code it will just throw an SEHExceptioninstance.
- 在已知 SEH 错误代码的情况下,它会将其映射到适当的 .Net 异常(即 OutOfMemoryException)
- 在不可映射(E_FAIL)或未知代码的情况下,它只会抛出一个SEHException实例。
Both of these will be caught with a simple "catch (Exception)" block.
这两个都将被一个简单的“catch (Exception)”块捕获。
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.
另一种可以跨越本机/托管边界的本机异常是 C++ 异常。我不确定它们是如何映射/处理的。我的猜测是,由于 Windows 在 SEH 之上实现了 C++ 异常,它们只是以相同的方式映射。
回答by nedruod
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:
但你仍然会有潜在的问题。根据MSDN,为了确保调用异常析构函数,您必须捕获如下:
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.
顺便说一句,如果您使用 (Exception e) 方法,您应该知道您可能遇到的不同类型的异常。RuntimeWrappedException 是任何托管非异常类型将被映射到的(对于可以抛出字符串的语言),其他类型将被映射,例如 OutOfMemoryException 和 AccessViolationException。COM Interop HRESULTS 或 E___FAIL 以外的异常将映射到 COMException,最后您将获得 E_FAIL 的 SEHException 或任何其他未映射的异常。
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.
那你该怎么办?最好的选择是不要从非托管代码中抛出异常!哈。真的,如果你有选择,设置障碍和失败会使选择哪个更糟,在异常处理期间有可能发生内存泄漏,或者不知道你的异常是什么类型。