Windows中的错误 - DWORD(GetLastError)vs HRESULT vs LSTATUS

Pau*_*aul 16 error-handling winapi wtl

我正在Win32 + WTL中进行一些编程,我对可用的错误类型感到困惑.

通常,我想检查错误,并将其提供给AtlGetErrorDescription(调用FormatMessage).

我的问题是:

  1. 有什么区别:

    • DWORD,归来GetLastError.
    • HRESULT,由例如CAtlFile包装器返回,HRESULT_FROM_WIN32用于转换DWORD.
    • LSTATUS,例如通过返回RegCreateKeyEx.
  2. 我可以提供哪些类型的错误FormatMessage?它的签名表示它接受HRESULT,但有很多例子GetLastError直接传递返回值FormatMessage.

Han*_*ant 25

它们只反映了Windows中使用的不同API:

  • GetLastError()返回一个winapi错误代码.从1开始的简单数字.它们通常从底层本机api错误代码映射.与ERROR_FILE_NOT_FOUND类似,从STATUS_OBJECT_NAME_NOT_FOUND文件系统驱动程序错误代码映射.Winapi错误代码在WinError.h SDK头文件中声明.您可以指望使用FORMAT_MESSAGE_FROM_SYSTEM选项从FormatMessage()获取描述性字符串.

  • HRESULT是COM错误代码.它由三个基本部分构成,高位表示严重性,中间位编码指示错误源的工具,低16位编码错误编号.HRESULT_FROM_WIN32()宏是一个帮助宏,用于将winapi错误代码映射到COM错误代码.它只将严重性设置为"失败",设施代码设置为7(winapi)并将错误代码复制到低位.有许多可能的COM错误代码,并且只有少数可以通过FormatMessage()转换为字符串.您应该使用ISupportErrorInfo接口来询问COM服务器是否可以通过IErrorInfo提供错误的描述.

  • LSTATUS是模糊的,RegCreateEx实际上返回LONG,只是winapi错误代码.它会弹出一些shell包装函数,比如SHGetValue().我常常很不清楚为什么shell团队会做它的功能.

  • 您的问题中没有提到,但值得注意的是本机API生成的错误代码.它们记录在ntstatus.h SDK标头中.winapi应该包装原生api,但这些错误代码有时会在边缘周围查看,特别是在例外情况下.大多数程序员都看到了0xc0000005(STATUS_ACCESS_VIOLATION)异常代码.0xc00000fd匹配此站点的名称.FormatMessage()可以将常用的字符串转换为字符串,只要它不是驱动程序生成的自定义错误代码即可.有几种api使用这些错误代码,即使它们在用户模式下运行.常见的例子是WIC和媒体基金会,否则没有强烈的暗示他们为什么喜欢这种方式.获取此类错误代码的字符串需要使用FormatMessage和FORMAT_MESSAGE_FROM_HMODULE选项.

  • `ERROR_SUCCESS`为0,与`S_OK`一样.`SUCCEEDED()`查找`> = 0`的任何`HRESULT`值,其中包括`S_FALSE`(1),这不是错误.`GetLastError()`返回错误的非零值.`HRESULT`使用值"<0"表示错误.要从`HRESULT`获取win32错误代码,如果`HRESULT_FACILITY()`返回`FACILITY_WIN32`(7),则可以使用`HRESULT_CODE()`. (3认同)
  • 谢谢你的详细解答.这是否意味着`FormatMessage`可以处理`GetLastError()`和`HRESULT_FROM_WIN32(GetLastError())`?另外,我不明白为什么有时ATL包装器返回WINAPI错误代码(例如`CRegKey`),有时返回`HRESULT`代码(例如`CAtlFile`).是否可以将结果保留在DWORD中,并将错误(如果有的话)传递给"FormatMessage"? (2认同)