如何在 C# 程序中使用标准 Windows 定义

How to use the standard Windows defines in a C# program

在 C# 程序中,我实现了以下函数:

int Test();

在程序的本机部分(用 C++ 编写)定义如下:

HRESULT Test();

或者可能:

DWORD Test();

因此,在实现功能时,我需要 return HRESULT 和来自 C# 部分的其他标准 Windows 代码。目前我已经实现如下:

public int Test()
{
  return 0x00000102; // WAIT_TIMEOUT
}

问题是如何在 C# 中使用人类可读的代码?我想写这样的东西:return WAIT_TIMEOUT; 就像我在 C++ 中所做的一样。

我正在寻找不需要下载外部库或类似内容的解决方案。仅标准 .NET。

顺便说一下,WAIT_TIMEOUT 不是 HRESULT,但我希望你理解这个问题 - 这个问题不是关于特殊情况,而是关于标准 Windows 常量.我只是想在 C# 中使用标准 Windows 定义(E_NOTIMPLWAIT_OBJECT_0S_FALSE 等)

我认为您正在寻找 WinAPI defines for C#。不确定这是否足够,但总的来说这个站点有一些其他定义和类似 C# 的东西。

选项 1:

使用枚举。您可以在此处找到一些错误代码:Common HRESULT values.

选项 2:

使用 VSConstants class,错误代码已经在那里定义为 int 常量。

选项 3:

为了更加符合 .NET,您的 public C# 方法应该抛出类似 .NET 的异常,而不是使用错误代码。为此,您可以使用 Marshal.ThrowExceptionForHR(int) 方法,也可以根据 this 页面进行一些映射。

   return 0x00000102; // WAIT_TIMEOUT

您需要先修复您的代码,这不是正确的 HRESULT。它们设置了高位以指示遇到错误情况。现在,您的 C++ 代码将假设您的 C# 方法没有失败,通常通过使用 SUCCEEDED() 或 FAILED() 宏来完成。

查看 WinError.h SDK 包含文件。它记录了 HRESULT 的结构,并定义了众所周知的 winapi 错误代码和 HRESULT。它还具有 HRESULT_FROM_WIN32() 的定义,这是一个将 win32 错误代码打包到适当的 HRESULT 中的辅助宏。

您可以像这样在 C# 代码中执行相同的操作:

static class Win32Interop { 
    const int WAIT_TIMEOUT = 0x102;

    static void ThrowWin32Error(int err) {
        unchecked {
            int hr = (int)0x80070000 + err;
            System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(hr);
        }
    }
}

现在你可以写:

public void test() {
    ThrowWin32Error(WAIT_TIMEOUT);
}

以这种看似复杂的方式执行此操作可确保异常具有合理的描述性消息 属性,并且您可以在 C++ 代码中提供比明显的 HRESULT 值更丰富的错误信息。使用 IErrorInfo 接口来执行此操作。另请注意,许多内置的 .NET 异常已经具有正确的 HResult 值。所以简单地抛出那个异常就足够了。否则不容易发现,您必须查看参考源。

请记住,使用 实际上 并非由 win32 函数生成的 Win32 错误代码是非常具有误导性的。任何试图诊断 0x80070102 的人都会寻找失败的操作系统调用。如果您的 C# 代码没有这样的代码,那么就会出现非常严重的令人头疼的问题。因此,我建议您这样做:

public void test() {
    throw new TimeoutException();
}

在您的 C++ 代码中生成 COR_E_TIMEOUT (0x80131505)。在调用 C# 代码时无论如何都需要熟悉 HRESULT 的类型。这些错误代码在 CorError.h SDK 包含文件中定义。