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

时间:2015-09-15 10:52:02

标签: c# c++ winapi native

在C#程序中,我实现了以下功能:

int Test();

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

HRESULT Test();

或可能:

DWORD Test();

因此,在实现函数时,我需要从C#部分返回HRESULT和其他标准Windows代码。此时我已按如下方式实施:

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

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

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

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

3 个答案:

答案 0 :(得分:3)

   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);
}

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

请记住,使用win32函数产生的实际的Win32错误代码非常容易引起误解。任何试图诊断0x80070102的人都会一直在寻找失败的操作系统调用。如果您的C#代码没有,那么接下来会非常严重。因此,我建议你这样做:

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

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

答案 1 :(得分:2)

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

答案 2 :(得分:2)

选项1:

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

选项2:

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

选项3:

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