Esta é a maneira correta de obter uma mensagem de erro do sistema para um HRESULT
(denominado hresult neste caso, ou você pode substituí-lo por 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;
}
A principal diferença entre isso e a resposta de David Hanak é o uso da FORMAT_MESSAGE_IGNORE_INSERTS
bandeira. O MSDN não está claro como as inserções devem ser usadas, mas Raymond Chen observa que você nunca deve usá-las ao recuperar uma mensagem do sistema, pois não há como saber quais inserções o sistema espera.
FWIW, se você estiver usando Visual C ++, você pode tornar sua vida um pouco mais fácil usando a _com_error
classe:
{
_com_error error(hresult);
LPCTSTR errorText = error.ErrorMessage();
// do something with the error...
//automatic cleanup when error goes out of scope
}
Não faz parte do MFC ou ATL diretamente, tanto quanto sei.
RegCreateKeyEx
retorna aLONG
. A documentação diz que posso usarFormatMessage
para recuperar o erro, mas preciso converter oLONG
em umHRESULT
.Lembre-se de que você não pode fazer o seguinte:
Conforme a classe é criada e destruída na pilha, deixa errorText apontar para um local inválido. Na maioria dos casos, esse local ainda conterá a string de erro, mas essa probabilidade diminui rapidamente ao gravar aplicativos encadeados.
Portanto, sempre faça da seguinte forma, conforme respondido por Shog9 acima:
fonte
_com_error
objeto é criado na pilha em ambos os exemplos. O termo que você está procurando é temporário . No exemplo anterior, o objeto é um temporário que é destruído no final da instrução.std::wstring strErrorText = _com_error(hresult).ErrorMessage();
Experimente isto:
fonte
Isso é mais uma adição à maioria das respostas, mas em vez de
LocalFree(errorText)
usar aHeapFree
função:No site do MSDN :
A atualização
descobri que
LocalFree
está na versão 10.0.10240.0 do SDK (linha 1108 no WinBase.h). No entanto, o aviso ainda existe no link acima.Atualização 2
Eu também sugeriria usar o
FORMAT_MESSAGE_MAX_WIDTH_MASK
sinalizador para organizar as quebras de linha nas mensagens do sistema.No site do MSDN :
Atualização 3
Parece haver 2 códigos de erro de sistema específicos que não retornam a mensagem completa usando a abordagem recomendada:
Por que FormatMessage cria apenas mensagens parciais para erros de sistema ERROR_SYSTEM_PROCESS_TERMINATED e ERROR_UNHANDLED_EXCEPTION?
fonte
Aqui está uma versão da função de David que lida com Unicode
}
fonte
_sntprintf_s
no caso UNICODE. A função leva o número de caracteres, então você quer_countof
ouARRAYSIZE
aka emsizeof(buffer) / sizeof(buffer[0])
vez desizeof
.Desde c ++ 11, você pode usar a biblioteca padrão em vez de
FormatMessage
:fonte
Conforme apontado em outras respostas:
FormatMessage
leva umDWORD
resultado, não umHRESULT
(normalmenteGetLastError()
).LocalFree
é necessário para liberar memória que foi alocada porFormatMessage
Eu peguei os pontos acima e acrescentei mais alguns para minha resposta:
FormatMessage
em uma classe para alocar e liberar memória conforme necessáriooperator LPTSTR() const { return ...; }
para que sua classe possa ser usada como uma stringEncontre uma versão mais completa do código acima aqui: https://github.com/stephenquan/FormatMessage
Com a classe acima, o uso é simplesmente:
fonte
O código a seguir é o código C ++ equivalente que escrevi em contraste com o ErrorExit () da Microsoft, mas ligeiramente alterado para evitar todas as macros e usar Unicode. A ideia aqui é evitar moldes e malhos desnecessários. Não consegui escapar de todos os elencos C, mas foi o melhor que consegui reunir. Pertencente a FormatMessageW (), que requer um ponteiro a ser alocado pela função de formato e o Id de erro de GetLastError (). O ponteiro após static_cast pode ser usado como um ponteiro wchar_t normal.
fonte