使用Win API可以获取HRESULT值的字符串表示吗?

79

Win API中是否有函数可以提取HRESULT值的字符串表示形式?

问题在于并非所有返回值都在MSDN中有文档说明,例如ExecuteInDefaultAppDomain()函数没有文档说明会返回"0x80070002 - 系统找不到指定的文件",但它确实返回了这个值! 因此,我想知道是否有一个通用的函数可以使用。


2
标题不同,但本质上答案与此问题的答案相同。 - Christian.K
4个回答

114
您可以使用_com_error
_com_error err(hr);
LPCTSTR errMsg = err.ErrorMessage();

如果由于某种原因您不想使用_com_error,仍然可以查看其源代码并了解其实现方式。
请不要忘记包含头文件comdef.h

8
为方便起见提供更完整的示例: inline CString GetMessageForHresult(HRESULT hr) { _com_error error(hr); CString cs; cs.Format(_T("错误码 0x%08x: %s"), hr, error.ErrorMessage()); return cs; } - nietras
5
需要包含头文件:#include<comdef.h> - Sahil Singh
2
@nietras 什么是 CString - Phani Rithvij
2
我们应该如何释放errMsg? - Nusrat Nuriyev
要使用 CString,请包含 atlstr.h 头文件。 - Matt Kleinsmith
显示剩余3条评论

36

自c++11起,此功能已内置于标准库中:

#include <system_error>

std::string message = std::system_category().message(hr)

3
这适用于系统错误,而不是通用的 HRESULT 错误代码。@che 你混淆了 HRESILTNT_STATUS。虽然它们具有类似的编码,但前者在 Windows API(COM)和 Windows Runtime 中广泛使用。在内核模式模块中,您都不会使用它们之一。 - IInspectable
<comdef.h> 中的 _com_error 很好地为您封装了所有内容,而不需要使用 "可怕的" <system_error> ... 不幸的是,这将把您推入到一个未解决的 Windows 遗留代码领域。我们实际上可能会重新实现它,减去 IErrorInfo 功能。不使用 std lib。 - Chef Gladiator

19

这个需要使用Windows API, 具体来说是FormatMessage。这里有一篇文章讲解如何使用:Retrieving Error Messages

对于Win32消息(HRESULT以0x8007开头的消息,即FACILITY_WIN32),您需要移除高位字。例如,在0x80070002中,需要使用0x0002调用FormatMessage。

然而,并不是所有类型的消息都适用。对于某些特定的消息(针对某个技术、供应商等),您需要加载相应的资源DLL,这并不总是一件容易的任务,因为您需要找到这个DLL。


3
0x8007中的7代表FACILITY_WIN32,而不是FACILITY_ITF。例如,请参阅“COM错误代码结构”http://msdn.microsoft.com/en-us/library/ms690088。 - Alessandro Jacopson
7
HRESULT_CODE(hr) 可以将其转换为 Win32 错误码。 - pronebird

3

这里是使用FormatMessage()的样例

LPTSTR SRUTIL_WinErrorMsg(int nErrorCode, LPTSTR pStr, WORD wLength )
{
    try
    {
        LPTSTR  szBuffer = pStr;
        int nBufferSize = wLength;

        //
        // prime buffer with error code
        //
        wsprintf( szBuffer, _T("Error code %u"), nErrorCode);

        //
        // if we have a message, replace default with msg.
        //
        FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
                NULL, nErrorCode,
                MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
                (LPTSTR) szBuffer,   
                nBufferSize,    
                NULL );
    }
    catch(...)
    {
    }
    return pStr;
} // End of SRUTIL_WinErrorMsg()

4
Win32是C语言编写的。上述内容是C和C++异常的混合体。我不知道FormatMessage或任何其他Win32函数会抛出C++异常?FormatMessage返回一个值,并且有充分的文档说明。并且该函数不能用于原始的HERROR值。使用HRESULT_CODE(hr)可以获取错误码,然后将其作为参数传递给该函数进行调用。 - Chef Gladiator
1
给那条评论点了负1的人,能否请您解释一下原因?我很感激学习。 - Chef Gladiator

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接