DllImport - PreserverSig和SetLastError属性

pko*_*iej 9 interop dllimport

在MSDN上,我找到了以下两个属性的描述:

PreserveSig将PreserveSig字段设置为true,以使用HRESULT或retval值直接转换非托管签名; 将其设置为false以自动将HRESULT或retval值转换为异常.默认情况下,PreserveSig字段为true.

SetLastError使调用者能够使用Marshal.GetLastWin32Error API函数来确定执行方法时是否发生错误.在Visual Basic中,默认值为true(这会增加一些开销); 在C#和C++中,默认值为false.

我的问题是:这两者如何相互关联?假设我将PreserveSig设置为'false' - 这意味着我应该将HRESULT转换为异常 - 如果非托管函数返回指示错误或没有错误发生的整数,那么如何将其转换为异常?

另外,为什么我需要调用GetLastWin32Error方法,如果我以某种方式设法使用PreserveSig提取异常?

亲切的问候PK

Ant*_*hyy 14

Win32函数几乎永远不会返回HRESULT.相反,它们返回一个BOOL或使用特殊值来指示错误(例如CreateFile返回INVALID_HANDLE_VALUE).它们将错误代码存储在每个线程变量中,您可以阅读它GetLastError().SetLastError=true指示封送程序在本机函数返回后读取此变量,并将错误代码存储在稍后可以读取的位置Marshal.GetLastWin32Error().这个想法是.NET运行时可能会在幕后调用其他Win32函数,这会在你有机会检查它之前搞乱p/invoke调用中的错误代码.

返回HRESULT(或等效的NTSTATUS)函数属于与Win32函数不同的抽象级别.通常这些函数与COM相关(在Win32之上)或从ntdll(在Win32之下),因此它们不使用Win32最后错误代码(尽管它们可能在内部调用Win32函数).

PreserveSig=false指示编组程序检查返回HRESULT,如果它不是成功代码,则创建并抛出包含该返回的异常HRESULT.然后,DllImported函数的托管声明具有void返回类型.

请记住,C#或VB编译器无法检查DllImported函数的非托管签名,因此它必须信任您所说的任何内容.如果你添加PreserveSig=false一个返回a之外的函数HRESULT,你会得到奇怪的结果(例如随机异常).如果你SetLastError=true设置了一个没有设置最后一个Win32错误代码的函数,你将获得垃圾而不是有用的错误代码.