我应该如何在 C++ 中正确使用 FormatMessage()?
没有:
- MFC
- ATL
如何使用 FormatMessage ()
获取 HRESULT
的错误文本?
HRESULT hresult = application.CreateInstance("Excel.Application");
if (FAILED(hresult))
{
// what should i put here to obtain a human-readable
// description of the error?
exit (hresult);
}
Without:
- MFC
- ATL
How can I use FormatMessage()
to get the error text for a HRESULT
?
HRESULT hresult = application.CreateInstance("Excel.Application");
if (FAILED(hresult))
{
// what should i put here to obtain a human-readable
// description of the error?
exit (hresult);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
以下是从系统返回
HRESULT
错误消息(在本例中名为 hresult,或者您可以将其替换为GetLastError()
)的正确方法:这与 David Hanak 的答案之间的区别在于使用
FORMAT_MESSAGE_IGNORE_INSERTS
标志。 MSDN 对于如何使用插入有点不清楚,但是 Raymond Chen 指出,您在检索系统消息时永远不应该使用它们,因为您无法知道系统需要哪些插入。FWIW,如果您使用的是 Visual C++,您可以使用
_com_error
类:据我所知,不直接属于 MFC 或 ATL。
Here's the proper way to get an error message back from the system for an
HRESULT
(named hresult in this case, or you can replace it withGetLastError()
):The key difference between this and David Hanak's answer is the use of the
FORMAT_MESSAGE_IGNORE_INSERTS
flag. MSDN is a bit unclear on how insertions should be used, but Raymond Chen notes that you should never use them when retrieving a system message, as you've no way of knowing which insertions the system expects.FWIW, if you're using Visual C++ you can make your life a bit easier by using the
_com_error
class:Not part of MFC or ATL directly as far as I'm aware.
请记住,您不能执行以下操作:
在堆栈上创建和销毁类时,使 errorText 指向无效位置。 在大多数情况下,该位置仍将包含错误字符串,但在编写线程应用程序时,这种可能性很快就会消失。
因此,总是按照上面 Shog9 的回答进行操作:
Keep in mind that you cannot do the following:
As the class is created and destroyed on the stack leaving errorText to point to an invalid location. In most cases this location will still contain the error string, but that likelihood falls away fast when writing threaded applications.
So always do it as follows as answered by Shog9 above:
尝试这个:
Try this:
从 c++11 开始,您可以使用标准库代替
FormatMessage
:Since c++11, you can use the standard library instead of
FormatMessage
:这更多的是对大多数答案的补充,但不使用
LocalFree(errorText)
,而是使用HeapFree
函数:来自 MSDN 站点:
更新
我发现
LocalFree
的 SDK 版本为 10.0.10240.0(WinBase.h 中的第 1108 行)。 但是,上面的链接中仍然存在警告。更新2
我还建议使用
FORMAT_MESSAGE_MAX_WIDTH_MASK
标志来整理系统消息中的换行符。来自 MSDN 站点:
更新3
似乎有 2 个特定的系统错误代码不会使用推荐的方法返回完整消息:
为什么 FormatMessage 只为 ERROR_SYSTEM_PROCESS_TERMINATED 和 ERROR_UNHANDLED_EXCEPTION 系统错误创建部分消息?
This is more an addition to the majority of the answers, but instead of using
LocalFree(errorText)
use theHeapFree
function:From the MSDN site:
Update
I found that
LocalFree
is in version 10.0.10240.0 of the SDK (line 1108 in WinBase.h). However, the warning still exists in the link above.Update 2
I would also suggest using the
FORMAT_MESSAGE_MAX_WIDTH_MASK
flag to tidy up line breaks in system messages.From the MSDN site:
Update 3
There appears to be 2 particular system error codes that do not return the full message using the recommended approach:
Why does FormatMessage only create partial messages for ERROR_SYSTEM_PROCESS_TERMINATED and ERROR_UNHANDLED_EXCEPTION system errors?
这是处理 Unicode 的 David 函数的一个版本
Here is a version of David's function that handles Unicode
正如其他答案中所指出的:
FormatMessage
采用DWORD
结果而不是HRESULT
(通常是GetLastError()
)。LocalFree
来释放由FormatMessage
分配的内存我采纳了上述几点,并为我的答案添加了更多内容:
FormatMessage
包装在根据需要分配和释放内存的类查找更完整的版本上面的代码在这里: https://github.com/stephenquan/FormatMessage
使用上面的类,用法很简单:
As pointed out in other answers:
FormatMessage
takes aDWORD
result not aHRESULT
(typicallyGetLastError()
).LocalFree
is needed to release memory that was allocated byFormatMessage
I took the above points and added a few more for my answer:
FormatMessage
in a class to allocate and release memory as neededoperator LPTSTR() const { return ...; }
so that your class can be used as a stringFind a more complete version of the above code here: https://github.com/stephenquan/FormatMessage
With the above class, the usage is simply:
下面的代码是我编写的 C++ 等效代码,与 Microsoft 的 ErrorExit() 但稍作修改以避免所有宏并使用 unicode。 这里的想法是避免不必要的强制转换和 malloc。 我无法逃脱所有的 C 演员阵容,但这是我能召集的最好的演员阵容。 与 FormatMessageW() 相关,它需要由格式函数分配一个指针以及来自 GetLastError() 的错误 ID。 static_cast之后的指针可以像普通的wchar_t指针一样使用。
The code below is code is the C++ equivalent I've written out in contrast to Microsoft's ErrorExit() but slightly altered to avoid all macros and use unicode. The idea here is to avoid unnecessary casts and mallocs. I couldn't escape all of the C casts but this is the best I could muster. Pertaining to FormatMessageW(), which requires a pointer to be allocated by the format function and the Error Id from the GetLastError(). The pointer after static_cast can be used like a normal wchar_t pointer.