【发布时间】:2009-03-23 15:57:52
【问题描述】:
我最近一直在编写大量涉及与 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 错误代码以及(通常)人类可读的错误描述,作为 Exception 对象的 Message 属性。但是,我一直认为最好修改/包装至少一些(如果不是全部)这些异常,以便它们提供稍微更面向上下文的错误消息,即在本机代码的任何情况下更有意义的错误消息是正在使用。为此,我考虑了几种替代方案:
-
在
Win32Exception的构造函数中指定自定义错误消息。throw new Win32Exception(Marshal.GetLastWin32Error(), "My custom error message."); -
将
Win32Exception包装在另一个异常对象中,以便保留原始错误代码和消息(Win32Exception现在是父异常的InnerException)。throw new Exception("My custom error message.", Win32Exception(Marshal.GetLastWin32Error())); 与2相同,只是使用另一个
Win32Exception作为包装异常。与 2 相同,但使用从
Exception派生的自定义类作为包装异常。与 2 相同,但在适当时使用 BCL(基类库)异常作为父异常。不确定在这种情况下将
InnerException设置为Win32Exception是否合适(可能是低级包装器,但不是更高级别/抽象的接口,这并不能清楚地表明Win32 互操作发生在后面场景?)
基本上我想知道的是:在 .NET 中处理 Win32 错误的推荐做法是什么?我看到它以各种不同的方式在开源代码中完成,但我很好奇是否有任何设计指南。如果没有,我会在这里对您的个人喜好感兴趣。 (也许你甚至没有使用上述方法?)
【问题讨论】:
标签: c# winapi exception win32exception