41

I'm messing around with some windows functions using p/invoke. Occasionally, I get an error code that is not ERROR_SUCCESS (such an odd name).

Is there a way to look these up within the program? Forexample, if I get error 1017. Can I tell the user

The system has attempted to load or restore a file into the registry, but the specified file is not in a registry file format. (ERROR_NOT_REGISTRY_FILE: 0x3F9)

Instead of

Error Code: 1017

Malfist
  • 31,179
  • 61
  • 182
  • 269

4 Answers4

114

I'm not sure if there's a niifty .NET wrapper, but you could call the FormatMessage API using P/Invoke.

See this answer for how it would normally be called from native code. Though the question refers to grabbing error codes from HRESULTs, the answer also applies for retreiving codes from the regular OS error codes coming from GetLastError/GetLastWin32Error).

EDIT: Thanks Malfist for pointing me to pinvoke.net, which includes alternative, managed API:

using System.ComponentModel;

string errorMessage = new Win32Exception(Marshal.GetLastWin32Error()).Message;
Console.WriteLine(errorMessage);
Community
  • 1
  • 1
Nick Meyer
  • 39,212
  • 14
  • 67
  • 75
  • 4
    http://www.pinvoke.net/default.aspx/kernel32/FormatMessage.html Says never to use FormatMessage – Malfist Oct 30 '09 at 16:33
  • @Malfist, thanks for pointing that out. There is a reply there that says it's okay as long as you're using Marshal.GetLastWin32Error to retrieve the error code. Nonetheless, it looks like Win32Exception is a better solution. – Nick Meyer Oct 30 '09 at 16:41
  • 4
    Note, though, that both of these solutions only get the descriptive error message; neither of these will get you the capitalized error name with underscores that you see in documentation (such as **ERROR_NOT_REGISTRY_FILE**). For anyone who lands here and is wondering about that, I recently asked [a question specifically about how to programmatically determine those error names](http://stackoverflow.com/q/30203717/1248365), and the answer turned out to be that you can't. They refer to constant names from winerror.h, a C++ include file provided in the Windows SDK. – Adi Inbar May 18 '15 at 15:46
  • This does not work for me, since `Marshal.GetLastWin32Error()` gives me 0 while `[DllImport("kernel32.dll")] private static extern uint GetLastError();` gives me the correct error value. (interestingly, if I set return type to `int` instead of `uint` I also get 0, and Marshal.GetLastWin32Error() has `int` as return type rather than `uint`). so, I dllimport GetLastError() with uint return type and then get the message by using `new Win32Exception((int) GetLastError()).Message` – matthias_buehlmann Apr 07 '21 at 14:45
  • 2
    @matthias_buehlmann Did you set `DllImportAttribute.SetLastError` set to `true`? See also: https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportattribute.setlasterror – Ramon de Klein May 21 '21 at 08:19
3

You could take the defines from winerror.h at Rensselaer Polytechnic Institute, and put them into an Enum:

public enum Win32ErrorCode : long
{
     ERROR_SUCCESS = 0L,
     NO_ERROR = 0L,
     ERROR_INVALID_FUNCTION = 1L,
     ERROR_FILE_NOT_FOUND = 2L,
     ERROR_PATH_NOT_FOUND = 3L,
     ERROR_TOO_MANY_OPEN_FILES = 4L,
     ERROR_ACCESS_DENIED = 5L,
     etc.
}

Then if your error code is in a variable error_code you would use :

Enum.GetName(typeof(Win32ErrorCode), error_code);
flapster
  • 53
  • 5
-1

I landed on this page while in search of a managed alternative to calling FormatMessage through P/Invoke.

As others have said, there is no way to get those capitalized, underscored names, short of looking them up in winerror.h, which I have seen reproduced online in various places where I landed in the course of searching for information about resolving specific status codes. A quick Google search, for winerror.h, itself, uncovered a page, at Rensselaer Polytechnic Instutute, where someone has helpfully extracted the #define statements from it.

Looking at it gave me an idea; I think there may be a way to get there, working from the source code of winerror.h, which I have, as part of the Windows Platform SDK that ships with every recent version of Microsoft Visual Studio.

Right now, I am in the middle of sorting out a pressing issue in the .NET assembly that brought me to this page. Then, I'll see what I can cobble together; this kind of challenge is right up my alley, and somebody threw down a gauntlet.

David A. Gray
  • 1,039
  • 12
  • 19
-7

Yes there's a function that does that but I don't remember what it is. In the mean time, you can use the error lookup tool (Tools->Error Lookup) to see what a particular code means from within Visual Studio.

Jon Norton
  • 2,969
  • 21
  • 20