Oto właściwy sposób, aby dostać się komunikat o błędzie z powrotem z układu na HRESULT
(o nazwie HRESULT w tym przypadku, czy można zastąpić go 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;
}
Kluczową różnicą między tą a Dawidem Hanakiem jest użycie flagi FORMAT_MESSAGE_IGNORE_INSERTS
. MSDN jest nieco niejasne, w jaki sposób należy używać wstawek, ale Raymond Chen notes that you should never use them podczas pobierania wiadomości systemowej, ponieważ nie masz możliwości sprawdzenia, które wstawienia system oczekuje.
FWIW, jeśli używasz Visual C++ można uczynić swoje życie trochę łatwiejsze za pomocą klasy _com_error
:
{
_com_error error(hresult);
LPCTSTR errorText = error.ErrorMessage();
// do something with the error...
//automatic cleanup when error goes out of scope
}
Nie jest częścią MFC lub ATL bezpośrednio o ile jestem świadomy.
Uwaga: ten kod używa hResult zamiast kodu błędu Win32: to są różne rzeczy! Możesz otrzymać tekst o zupełnie innym błędzie niż ten, który faktycznie wystąpił. –
Doskonały punkt, @Andrei - i nawet jeśli błąd * jest * błędem Win32, ta procedura zakończy się sukcesem, jeśli jest to błąd * systemu * - solidny mechanizm obsługi błędów musiałby być świadomy źródła błąd, sprawdź kod przed wywołaniem FormatMessage i zamiast tego zapytaj o inne źródła. – Shog9
@AndreiBelogortseff Skąd mogę wiedzieć, co używać w każdym przypadku? Na przykład 'RegCreateKeyEx' zwraca wartość' LONG'. Jego dokumenty mówią, że mogę użyć 'FormatMessage', aby pobrać błąd, ale muszę rzucić' LONG' w 'HRESULT'. – csl