Aquí es la forma adecuada para obtener un mensaje de error vuelto del sistema para un HRESULT
(hresult nombrado en este caso, o puede reemplazarlo con GetLastError()
):
LPTSTR errorText = NULL;
FormatMessage(
// use system message tables to retrieve error text
FORMAT_MESSAGE_FROM_SYSTEM
// allocate buffer on local heap for error text
|FORMAT_MESSAGE_ALLOCATE_BUFFER
// Important! will fail otherwise, since we're not
// (and CANNOT) pass insertion parameters
|FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, // unused with FORMAT_MESSAGE_FROM_SYSTEM
hresult,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR)&errorText, // output
0, // minimum size for output buffer
NULL); // arguments - see note
if (NULL != errorText)
{
// ... do something with the string `errorText` - log it, display it to the user, etc.
// release memory allocated by FormatMessage()
LocalFree(errorText);
errorText = NULL;
}
La diferencia clave entre esto y la respuesta de David Hanak es el uso de la bandera FORMAT_MESSAGE_IGNORE_INSERTS
. MSDN no está nada claro sobre cómo se deben usar las inserciones, pero Raymond Chen notes that you should never use them al recuperar un mensaje del sistema, ya que no tiene forma de saber qué inserciones espera el sistema.
Fwiw, si está utilizando Visual C++ puede hacer su vida un poco más fácil mediante el uso de la clase _com_error
:
{
_com_error error(hresult);
LPCTSTR errorText = error.ErrorMessage();
// do something with the error...
//automatic cleanup when error goes out of scope
}
No forma parte del MFC o ATL directamente Por lo que yo soy consciente.
Cuidado: este código utiliza hResult en lugar de un código de error Win32: ¡esas son cosas diferentes! Puede obtener el texto de un error completamente diferente al que realmente ocurrió. –
Excelente punto, @Andrei - y de hecho, incluso si el error * es * un error de Win32, esta rutina solo tendrá éxito si se trata de un error * system * - un mecanismo robusto de manejo de errores debería conocer la fuente del error, examine el código antes de llamar a FormatMessage y quizás consulte otras fuentes en su lugar. – Shog9
@AndreiBelogortseff ¿Cómo puedo saber qué usar en cada caso? Por ejemplo, 'RegCreateKeyEx' devuelve un' LONG'. Sus documentos dicen que puedo usar 'FormatMessage' para recuperar el error, pero tengo que convertir el' LONG' en 'HRESULT'. – csl