最近,我一直在写很多涉及与Win32 API互操作的代码,并且开始怀疑什么是处理由Windows API函数调用引起的 native (非托管)错误的最佳方法。

当前,对 native 函数的调用如下所示:

// 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属性。但是,我一直认为建议至少修改/包装一些(如果不是全部)异常,以便它们给出稍微更多的面向上下文的错误消息,即在任何情况下 native 代码都有意义。正在使用。我已经考虑了几种替代方法:
  • 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是否合适(也许是低级别的包装程序,而不是较高级别的/抽象的接口(interface),这种接口(interface)不能使Win32互操作明显在幕后发生?)

  • 从本质上讲,我想知道的是:处理.NET中Win32错误的推荐做法是什么?我看到它以各种不同的方式在开源代码中完成,但是我很好奇是否有任何设计指南。如果没有,我会对您的个人喜好感兴趣。 (也许您甚至都不使用上述方法?)

    最佳答案

    这并不是真正针对Win32异常的。问题是,什么时候应该用两种不同的异常派生类型来标识两种不同的错误情况,什么时候应该抛出具有不同值的相同类型呢?

    不幸的是,如果不事先知道您的代码将被调用的所有情况,这是无法回答的。:)这是只能按类型过滤异常的问题。广义上讲,如果您强烈认为以不同方式对待两个错误情况将很有用,请抛出不同的类型。

    否则,通常仅需要将Exception.Message返回的字符串记录或显示给用户。

    如果还有其他信息,请用您自己的更高级的东西包装Win32Exception。例如,您正在尝试对文件执行操作,而您正在其下运行的用户没有执行此操作的权限。捕获Win32Exception,将其包装在您自己的异常类中,其消息给出文件名和正在尝试的操作,后跟内部异常的消息。

    关于c# - 引发Win32Exception,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/673956/

    10-09 03:12