Hier ist der richtige Weg, um eine Fehlermeldung vom System für ein HRESULT
(in diesem Fall hresult genannt, oder Sie können es durch ersetzen GetLastError()
) zurück zu erhalten:
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;
}
Der Hauptunterschied zwischen dieser und der Antwort von David Hanak ist die Verwendung der FORMAT_MESSAGE_IGNORE_INSERTS
Flagge. MSDN ist etwas unklar, wie Einfügungen verwendet werden sollen, aber Raymond Chen merkt an, dass Sie sie niemals verwenden sollten beim Abrufen einer Systemnachricht , da Sie nicht wissen können, welche Einfügungen das System erwartet.
FWIW, wenn Sie Visual C ++ verwenden, können Sie Ihr Leben ein bisschen einfacher machen, indem Sie die _com_error
Klasse verwenden:
{
_com_error error(hresult);
LPCTSTR errorText = error.ErrorMessage();
// do something with the error...
//automatic cleanup when error goes out of scope
}
Soweit mir bekannt, nicht direkt Teil von MFC oder ATL.
RegCreateKeyEx
zurückLONG
. Seine docs sagt ich verwenden kann , umFormatMessage
den Fehler zu holen, aber ich das werfen mußLONG
in einHRESULT
.Beachten Sie, dass Sie Folgendes nicht tun können:
Während die Klasse auf dem Stapel erstellt und zerstört wird, bleibt errorText auf einen ungültigen Speicherort verweisen. In den meisten Fällen enthält dieser Speicherort weiterhin die Fehlerzeichenfolge, aber diese Wahrscheinlichkeit nimmt beim Schreiben von Thread-Anwendungen schnell ab.
Machen Sie es also immer wie folgt, wie von Shog9 oben beantwortet:
quelle
_com_error
Objekt wird in beiden Beispielen auf dem Stapel erstellt . Der gesuchte Begriff ist vorübergehend . Im ersten Beispiel ist das Objekt ein temporäres Objekt, das am Ende der Anweisung zerstört wird.std::wstring strErrorText = _com_error(hresult).ErrorMessage();
Versuche dies:
quelle
Hier ist eine Version von Davids Funktion, die Unicode verarbeitet
}}
quelle
_sntprintf_s
im UNICODE-Fall nicht die richtige Puffergröße übergeben . Die Funktion nimmt die Anzahl der Zeichen an, also möchten Sie_countof
oderARRAYSIZE
akasizeof(buffer) / sizeof(buffer[0])
anstelle vonsizeof
.Dies ist eher eine Ergänzung zu den meisten Antworten, aber anstatt
LocalFree(errorText)
dieHeapFree
Funktion zu verwenden:Von der MSDN-Site :
Update
Ich habe festgestellt, dass
LocalFree
es sich um Version 10.0.10240.0 des SDK handelt (Zeile 1108 in WinBase.h). Die Warnung ist jedoch weiterhin im obigen Link vorhanden.Update 2
Ich würde auch vorschlagen, das
FORMAT_MESSAGE_MAX_WIDTH_MASK
Flag zu verwenden, um Zeilenumbrüche in Systemnachrichten aufzuräumen.Von der MSDN-Site :
Update 3
Es scheint 2 bestimmte Systemfehlercodes zu geben, die nicht die vollständige Nachricht mit dem empfohlenen Ansatz zurückgeben:
Warum erstellt FormatMessage nur Teilmeldungen für Systemfehler ERROR_SYSTEM_PROCESS_TERMINATED und ERROR_UNHANDLED_EXCEPTION?
quelle
Seit c ++ 11 können Sie die Standardbibliothek anstelle von
FormatMessage
:quelle
Wie in anderen Antworten ausgeführt:
FormatMessage
nimmt einDWORD
Ergebnis nicht einHRESULT
(normalerweiseGetLastError()
).LocalFree
wird benötigt, um Speicher freizugeben, der von zugewiesen wurdeFormatMessage
Ich nahm die obigen Punkte und fügte ein paar weitere für meine Antwort hinzu:
FormatMessage
in eine Klasse ein, um Speicher nach Bedarf zuzuweisen und freizugebenoperator LPTSTR() const { return ...; }
damit Ihre Klasse als Zeichenfolge verwendet werden kannEine vollständigere Version des obigen Codes finden Sie hier: https://github.com/stephenquan/FormatMessage
Mit der obigen Klasse ist die Verwendung einfach:
quelle
Der folgende Code ist Code ist das C ++ - Äquivalent, das ich im Gegensatz zu Microsoft's ErrorExit () geschrieben habe, aber leicht geändert, um alle Makros zu vermeiden und Unicode zu verwenden. Die Idee hier ist, unnötige Abgüsse und Mallocs zu vermeiden. Ich konnte nicht allen C-Casts entkommen, aber das ist das Beste, was ich aufbringen konnte. Bezieht sich auf FormatMessageW (), für das ein Zeiger von der Formatierungsfunktion und der Fehler-ID aus GetLastError () zugewiesen werden muss. Der Zeiger nach static_cast kann wie ein normaler wchar_t-Zeiger verwendet werden.
quelle