P/Invoke 不安全代码应该出现哪些异常?
在我的解决方案中,我编写了以下内容:
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern unsafe bool CopyFileEx(string lpExistingFileName,
string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData,
Boolean* pbCancel, CopyFileFlags dwCopyFlags);
...
bool result;
unsafe{
result = CopyFileEx(sourceFile, targetFile, null, IntPtr.Zero,
null /* pointer */, 0);
}
if(!result)
Win32Exception exc = new Win32Exception(Marshal.GetLastWin32Error());
// parameter could be omitted according to Win32Exception constructor
// implementation
假设 CopyFileEx 是使用 DllImport 属性的 SetLastError = true 参数导出的,我是否有机会在这里得到任何未停止的异常?
我对包装在 RuntimeWrappedException 实例中的非 CLR 异常特别感兴趣。在 C++ 中,“throw 1”是一个有效的构造。那么,我应该从此类 P/Invoke 调用中期待哪些异常,以及从哪里可以获得有关异常的此类信息(MSDN 没有提及有关 CopyFileEx 的异常)?
In my solution I've written the following:
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern unsafe bool CopyFileEx(string lpExistingFileName,
string lpNewFileName, CopyProgressRoutine lpProgressRoutine, IntPtr lpData,
Boolean* pbCancel, CopyFileFlags dwCopyFlags);
...
bool result;
unsafe{
result = CopyFileEx(sourceFile, targetFile, null, IntPtr.Zero,
null /* pointer */, 0);
}
if(!result)
Win32Exception exc = new Win32Exception(Marshal.GetLastWin32Error());
// parameter could be omitted according to Win32Exception constructor
// implementation
In the assumption that CopyFileEx was exported with SetLastError = true parameter of DllImport attribute, do I have a chance to get any unhalted exception here?
I'm specifically interested in non-CLR exceptions which are wrapped in RuntimeWrappedException instance. In C++ "throw 1" is a valid construct. So what exceptions should I expect from such P/Invoke calls and where I can obtain such information regarding exceptions (MSDN says nothing regarding exceptions from CopyFileEx)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果 DLL 使用 Win32 结构化异常处理系统,则 DLL 抛出的任何异常都将被转换为
OutOfMemoryException
、AccessViolationException
、NullReferenceException
(很少见) ),或SEHException
。RuntimeWrappedException
仅在托管 C++ 抛出非Exception
派生对象时使用。它不用于非托管 DLL。如果您有一个执行抛出 1
的托管 C++ DLL,那么您可以捕获RuntimeWrappedException
。SEHException
充当来自非托管 DLL 的不可映射 SEH 异常类型的捕获器。这将包括任何 C++ 类或throw 1
示例。 AFAIK,没有办法从SEHException
中提取 C++ 特定的异常信息,尽管我确信如果你足够努力的话它是可以破解的。请注意,有一些 DLL 不使用 Win32 结构化异常处理系统。最值得注意的是 Cygwin DLL。在这种情况下,任何 C++ 异常都可能导致进程崩溃或至少导致线程崩溃。当然,所有 Windows DLL(包括定义 CopyFileEx 的 DLL)都使用 Win32 结构化异常处理,Microsoft C++ 编译器创建的任何非托管 DLL 也是如此。
另请注意,Win32 API(包括 CopyFileEx)通常不会使用 Win32 结构化异常报告错误;他们通过
GetLastError
报告它们。让大多数 Win32 函数抛出 Win32 结构化异常的唯一方法是向其传递极其无效的参数(例如要求它写入 ntdll.dll 的中间)。If a DLL uses the Win32 structured exception handling system, then any exceptions thrown by the DLL will be translated to
OutOfMemoryException
,AccessViolationException
,NullReferenceException
(rarely), orSEHException
.RuntimeWrappedException
is only used when managed C++ throws a non-Exception
-derived object. It is not used for unmanaged DLLs. If you had a managed C++ DLL that did athrow 1
, then you could catchRuntimeWrappedException
.SEHException
acts as a catch-all for the unmappable types of SEH exceptions from unmanaged DLLs. This would include any C++ class, or thethrow 1
example. AFAIK, there is no way to pull the C++-specific exception info out ofSEHException
, though I'm sure it's hackable if you try hard enough.Note that there are a few DLLs that do not use the Win32 structured exception handling system. Most notably Cygwin DLLs. In that case, any C++ exception is likely to crash the process or at least your thread. Naturally, all the Windows DLLs (including the one defining
CopyFileEx
) do use Win32 structured exception handling, as do any unmanaged DLLs created by Microsoft's C++ compiler.Also note that the Win32 API (including
CopyFileEx
) does not normally report errors using Win32 structured exceptions; they report them viaGetLastError
. The only way to get most Win32 functions to throw a Win32 structured exception is to pass it wildly invalid arguments (such as asking it to write into the middle ofntdll.dll
).