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

2

In C# program I have an implementation of the following function:

int Test();

Which is defined in the native part of a program (which is written in C++) as follows:

HRESULT Test();

or possibly:

DWORD Test();

So while implementing the functions I need to return HRESULT and other standard Windows codes from the C# part. At this moment I've implemented it as follows:

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

The question is how can I use the human-readable codes in C#? I want to write something like: return WAIT_TIMEOUT; in the same manner as I can do it in C++.

I'm seeking a solution which doesn't require to download external libraries or something like that. Only standard .NET.

And by the way WAIT_TIMEOUT isn't a HRESULT, but I hope you understand the question - the question isn't about exceptional situations, but about standard Windows constants. I'm just trying to use standard Windows defines in C# (E_NOTIMPL, WAIT_OBJECT_0, S_FALSE, etc.)

c#
c++
winapi
native
asked on Stack Overflow Sep 15, 2015 by Kirill V. Lyadvinsky • edited Sep 16, 2015 by Kirill V. Lyadvinsky

3 Answers

3
   return 0x00000102; // WAIT_TIMEOUT

You need to start by fixing your code, that is not a proper HRESULT. They have the high bit set to indicate that an error condition was encountered. Right now your C++ code will assume that your C# method did not fail, normally done by using the SUCCEEDED() or FAILED() macros.

Have a look-see at the WinError.h SDK include file. It documents the structure of an HRESULT and has definitions for the well-known winapi error codes and HRESULTs. It also has a definition for HRESULT_FROM_WIN32(), a helper macro that packages a win32 error code into an appropriate HRESULT.

You can do the same in C# code like this:

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

Now you can write:

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

Doing it in this seemingly elaborate way ensures that the exception has a reasonably descriptive Message property and that you can provide richer error info in your C++ code beyond the stark HRESULT value. Use the IErrorInfo interface to do so. Also note that many built-in .NET exceptions already have the proper HResult value. So simply throwing that exception is enough. Not otherwise simple to discover, you'd have to look at the Reference Source.

Do keep in mind that using Win32 error codes that were not actually produced by win32 functions is very misleading. Anybody that tries to diagnose 0x80070102 will always look for a failing operating system call. If your C# code doesn't have one then pretty serious head-scratching ensues. I will therefore recommend you do it this way:

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

Which produces COR_E_TIMEOUT (0x80131505) in your C++ code. The kind of HRESULTs you need to get familiar with anyway when you call C# code. These error codes are defined in the CorError.h SDK include file.

answered on Stack Overflow Sep 15, 2015 by Hans Passant • edited Sep 15, 2015 by Hans Passant
2

I think you're looking for WinAPI defines for C#. Not sure if this is enough, but overall afair this site has some other defines and stuff like that for C#.

answered on Stack Overflow Sep 15, 2015 by Ivan0x32
2

Option 1:

Use an enumeration. You can find some error codes here: Common HRESULT values.

Option 2:

Use the VSConstants class, the error codes are already defined there as int constants.

Option 3:

To be more .NET conform, your public C# methods should rather throw .NET-like exceptions instead of using error codes. To do so, you can either use the Marshal.ThrowExceptionForHR(int) method, or you can do some mapping based on this page.

answered on Stack Overflow Sep 15, 2015 by György Kőszeg

User contributions licensed under CC BY-SA 3.0