The GetLastError function returns the calling thread's last-error code value. The last-error code is maintained on a per-thread basis. Multiple threads do not overwrite each other's last-error code.
An application can retrieve the last-error code by using the GetLastError function; the error code may tell more about what actually occurred to make the function fail. The documentation for system functions will indicate the conditions under which the function sets the last-error code.
If your application needs more details about an error, it can retrieve the last-error code using the GetLastError function and display a description of the error using the FormatMessage function. The following example includes an error-handling function that prints the error message and terminates the process.
//Returns the last Win32 error, in string format. Returns an empty string if there is no error.
std::string GetLastErrorAsString()
{
//Get the error message ID, if any.
DWORD errorMessageID = ::GetLastError();
if(errorMessageID == 0) {
return std::string(); //No error message has been recorded
}
LPSTR messageBuffer = nullptr;
//Ask Win32 to give us the string version of that message ID.
//The parameters we pass in, tell Win32 to create the buffer that holds the message for us (because we don't yet know how long the message string will be).
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
//Copy the error message into a std::string.
std::string message(messageBuffer, size);
//Free the Win32's string's buffer.
LocalFree(messageBuffer);
return message;
}
Updated (11/2017) to take into consideration some comments.
Easy example:
wchar_t buf[256];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
buf, (sizeof(buf) / sizeof(wchar_t)), NULL);
MSDN has some sample code that demonstrates how to use FormatMessage()
and GetLastError()
together: Retrieving the Last-Error Code
GetLastError returns a numerical error code. To obtain a descriptive error message (e.g., to display to a user), you can call FormatMessage:
// This functions fills a caller-defined character buffer (pBuffer)
// of max length (cchBufferLength) with the human-readable error message
// for a Win32 error code (dwErrorCode).
//
// Returns TRUE if successful, or FALSE otherwise.
// If successful, pBuffer is guaranteed to be NUL-terminated.
// On failure, the contents of pBuffer are undefined.
BOOL GetErrorMessage(DWORD dwErrorCode, LPTSTR pBuffer, DWORD cchBufferLength)
{
if (cchBufferLength == 0)
{
return FALSE;
}
DWORD cchMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, /* (not used with FORMAT_MESSAGE_FROM_SYSTEM) */
dwErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
pBuffer,
cchBufferLength,
NULL);
return (cchMsg > 0);
}
In C++, you can simplify the interface considerably by using the std::string class:
#include <Windows.h>
#include <system_error>
#include <memory>
#include <string>
typedef std::basic_string<TCHAR> String;
String GetErrorMessage(DWORD dwErrorCode)
{
LPTSTR psz{ nullptr };
const DWORD cchMsg = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_IGNORE_INSERTS
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, // (not used with FORMAT_MESSAGE_FROM_SYSTEM)
dwErrorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPTSTR>(&psz),
0,
NULL);
if (cchMsg > 0)
{
// Assign buffer to smart pointer with custom deleter so that memory gets released
// in case String's c'tor throws an exception.
auto deleter = [](void* p) { ::LocalFree(p); };
std::unique_ptr<TCHAR, decltype(deleter)> ptrBuffer(psz, deleter);
return String(ptrBuffer.get(), cchMsg);
}
else
{
auto error_code{ ::GetLastError() };
throw std::system_error( error_code, std::system_category(),
"Failed to retrieve error message string.");
}
}
NOTE: These functions also work for HRESULT values. Just change the first parameter from DWORD dwErrorCode to HRESULT hResult. The rest of the code can remain unchanged.
FORMAT_MESSAGE_IGNORE_INSERTS
flag. See The importance of the FORMAT_MESSAGE_IGNORE_INSERTS flag for more information.This answer has been incorporated from Stack Overflow Documentation. The following users have contributed to the example: stackptr, Ajay, Cody Gray♦, IInspectable.
FormatMessage will turn GetLastError's integer return into a text message.
Since c++11, you can use the standard library instead of FormatMessage
:
#include <system_error>
std::string GetLastErrorAsString(){
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0) {
return std::string(); //No error message has been recorded
} else {
return std::system_category().message(errorMessageID);
}
}
In general, you need to use FormatMessage
to convert from a Win32 error code to text.
From the MSDN documentation:
Formats a message string. The function requires a message definition as input. The message definition can come from a buffer passed into the function. It can come from a message table resource in an already-loaded module. Or the caller can ask the function to search the system's message table resource(s) for the message definition. The function finds the message definition in a message table resource based on a message identifier and a language identifier. The function copies the formatted message text to an output buffer, processing any embedded insert sequences if requested.
The declaration of FormatMessage:
DWORD WINAPI FormatMessage(
__in DWORD dwFlags,
__in_opt LPCVOID lpSource,
__in DWORD dwMessageId, // your error code
__in DWORD dwLanguageId,
__out LPTSTR lpBuffer,
__in DWORD nSize,
__in_opt va_list *Arguments
);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With