Voici la bonne façon de récupérer un message d'erreur du système pour un HRESULT
(nommé hresult dans ce cas, ou vous pouvez le remplacer par 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 principale différence entre cela et la réponse de David Hanak est l'utilisation du FORMAT_MESSAGE_IGNORE_INSERTS
drapeau. MSDN est un peu incertain sur la façon dont les insertions doivent être utilisées, mais Raymond Chen note que vous ne devriez jamais les utiliser lors de la récupération d'un message système, car vous n'avez aucun moyen de savoir à quelles insertions le système attend.
FWIW, si vous utilisez Visual C ++, vous pouvez vous simplifier la vie un peu en utilisant la _com_error
classe:
{
_com_error error(hresult);
LPCTSTR errorText = error.ErrorMessage();
// do something with the error...
//automatic cleanup when error goes out of scope
}
Ne fait pas partie de MFC ou ATL directement pour autant que je sache.
RegCreateKeyEx
renvoie unLONG
. Sa documentation indique que je peux utiliserFormatMessage
pour récupérer l'erreur, mais je doisLONG
convertir le fichier dans un fichierHRESULT
.Gardez à l'esprit que vous ne pouvez pas effectuer les opérations suivantes:
Au fur et à mesure que la classe est créée et détruite sur la pile, le message errorText pointe vers un emplacement non valide. Dans la plupart des cas, cet emplacement contiendra toujours la chaîne d'erreur, mais cette probabilité diminue rapidement lors de l'écriture d'applications threadées.
Alors faites-le toujours comme suit, comme répondu par Shog9 ci-dessus:
la source
_com_error
objet est créé sur la pile dans vos deux exemples. Le terme que vous recherchez est temporaire . Dans le premier exemple, l'objet est un temporaire qui est détruit à la fin de l'instruction.std::wstring strErrorText = _com_error(hresult).ErrorMessage();
Essaye ça:
la source
C'est plus un ajout à la majorité des réponses, mais au lieu d'utiliser,
LocalFree(errorText)
utilisez laHeapFree
fonction:Depuis le site MSDN :
Mise à jour que
j'ai trouvée
LocalFree
dans la version 10.0.10240.0 du SDK (ligne 1108 dans WinBase.h). Cependant, l'avertissement existe toujours dans le lien ci-dessus.Mise à jour 2
Je suggérerais également d'utiliser le
FORMAT_MESSAGE_MAX_WIDTH_MASK
drapeau pour ranger les sauts de ligne dans les messages système.Depuis le site MSDN :
Mise à jour 3
Il semble y avoir 2 codes d'erreur système particuliers qui ne renvoient pas le message complet en utilisant l'approche recommandée:
Pourquoi FormatMessage ne crée-t-il que des messages partiels pour les erreurs système ERROR_SYSTEM_PROCESS_TERMINATED et ERROR_UNHANDLED_EXCEPTION?
la source
Voici une version de la fonction de David qui gère Unicode
}
la source
_sntprintf_s
dans le cas UNICODE. La fonction prend le nombre de caractères, donc vous voulez_countof
ouARRAYSIZE
aka à lasizeof(buffer) / sizeof(buffer[0])
place dusizeof
.Depuis c ++ 11, vous pouvez utiliser la bibliothèque standard au lieu de
FormatMessage
:la source
Comme indiqué dans d'autres réponses:
FormatMessage
prend unDWORD
résultat pas unHRESULT
(généralementGetLastError()
).LocalFree
est nécessaire pour libérer la mémoire allouée parFormatMessage
J'ai pris les points ci-dessus et en ai ajouté quelques autres pour ma réponse:
FormatMessage
dans une classe pour allouer et libérer de la mémoire si nécessaireoperator LPTSTR() const { return ...; }
pour que votre classe puisse être utilisée comme une chaîneTrouvez une version plus complète du code ci-dessus ici: https://github.com/stephenquan/FormatMessage
Avec la classe ci-dessus, l'utilisation est simplement:
la source
Le code ci-dessous est le code est l'équivalent C ++ que j'ai écrit contrairement à ErrorExit () de Microsoft mais légèrement modifié pour éviter toutes les macros et utiliser unicode. L'idée ici est d'éviter les moulages et les mallocs inutiles. Je n'ai pas pu échapper à tous les lancers C mais c'est le meilleur que je puisse rassembler. Concernant FormatMessageW (), qui nécessite qu'un pointeur soit alloué par la fonction de format et l'ID d'erreur de GetLastError (). Le pointeur après static_cast peut être utilisé comme un pointeur wchar_t normal.
la source