我最近一直在编写很多涉及与 Win32 API 互操作的代码,并且开始想知道处理由调用 Windows API 函数引起的本机(非托管)错误的最佳方法是什么。
目前,对本机函数的调用如下所示:
// NativeFunction returns true when successful and false when an error
// occurred. When an error occurs, the MSDN docs usually tell you that the
// error code can be discovered by calling GetLastError (as long as the
// SetLastError flag has been set in the DllImport attribute).
// Marshal.GetLastWin32Error is the equivalent managed function, it seems.
if (!WinApi.NativeFunction(param1, param2, param3))
throw new Win32Exception();
引发异常的行可以等效地重写,我相信:
throw new Win32Exception(Marshal.GetLastWin32Error());
现在,这一切都很好,因为它适当地引发了一个异常,其中包含设置的 Win32 错误代码以及(通常)人类可读的错误描述作为Message
Exception 对象的属性。但是,我一直认为建议至少修改/包装这些异常中的一些(如果不是全部),以便它们提供稍微更面向上下文的错误消息,即在本机代码的任何情况下更有意义的错误消息是正在使用。为此,我考虑了几种替代方案:
在构造函数中为
Win32Exception
.throw new Win32Exception(Marshal.GetLastWin32Error(), "My custom error message.");
将 包装
Win32Exception
在另一个 Exception 对象中,以便保留原始错误代码和消息(Win32Exception
现在是InnerException
父异常的)。throw new Exception("My custom error message.", Win32Exception(Marshal.GetLastWin32Error()));
与 2 相同,除了使用另一个
Win32Exception
作为包装异常。与 2 相同,但使用派生自的自定义类
Exception
作为包装异常。与 2 相同,除了在适当时使用 BCL(基类库)异常作为父异常。不确定在这种情况下是否适合将 设置为
InnerException
(Win32Exception
可能是低级包装器,但不是更高级别/抽象的接口,这不会使 Win32 互操作在幕后发生明显?)
基本上我想知道的是:在 .NET 中处理 Win32 错误的推荐做法是什么?我看到它以各种不同的方式在开源代码中完成,但我很好奇是否有任何设计指南。如果没有,我会在这里对您的个人喜好感兴趣。(也许您甚至没有使用上述方法?)