在计算机编程领域中，**HRESULT**是一种在 Windows 操作系统中使用的数据类型，并且曾更早在 IBM/Microsoft OS/2 操作系统中使用。用来表示错误和警告的情况。

HRESULT的最初目的是为了防止OS/2操作系统的不同子系统中的错误代码之间的冲突，正式地规定第三方和微软内部使用的错误代码范围。它是基于数字的错误代码，HRESULT中的各个位编码包含有关错误代码的性质及其来源的信息。

HRESULT 错误码在COM编程领域很常见，它们构成了标准化的COM错误处理约定的基础。

HRESULT 格式
----------

HRESULT值有32位，分为三个字段：严重性代码、设施代码和错误代码。严重性代码指示返回值是表示信息、警告还是错误。设施代码标识负责错误的系统区域。错误代码是分配用于表示异常的唯一编号。 每个异常映射到不同的HRESULT。

HRESULT的结构如下：

|  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |  |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Bit | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
| Field | S | R | C | N | X | Facility | Code |

### 格式细节

* S - 严重性 - 表示成功或失败
	+ 0 - 成功
	+ 1 - 失败
* R - 设施代码的保留部分，对应于NT的第二严重性位。
	+ 1 - 严重故障
* C - 第三方。 此位指定值是第三方定义还是Microsoft定义的。
	+ 0 - Microsoft-定义
	+ 1 - 第三方定义
* N - 保留部分设施代码。 用于指示映射的NT状态值。
* X - 保留部分设施代码。 保留供内部使用。 用于指示不是状态值的HRESULT值，而是用于显示字符串的消息标识。
* 设施 - 表示引发错误的系统服务. 示例设施代码如下所示（完整列表请参见 ).
	+ 1 - RPC
	+ 2 - 调度（COM调度）
	+ 3 - 存储 (OLE 存储)
	+ 4 - ITF (COM/OLE 接口管理)
	+ 7 - Win32 (原始 Win32 错误代码)
	+ 8 - Windows
	+ 9 - SSPI
	+ 10 - 控制
	+ 11 - CERT (客户端或服务器认证)
	+ ...
* Code - 设施的状态代码

ITF设施代码随后被再次用作COM组件可以定义自己的组件特定错误代码的范围。

HRESULT 是如何工作的
--------------

HRESULT是一个不透明的结果句柄，定义为从函数成功返回为0或正值，对失败为负值。一般的, 成功的函数返回 `S_OK` HRESULT 值 (这个HRESULT等于0)。但在极少数情况下，函数可能返回成功代码与附加信息，例如`S_FALSE=0x01`。

当显示HRESULT时，它们通常呈现为 无符号十六进制值, 通常用 `0x` 做前缀。在这种情况下，可以通过以十六进制数字8或更高开始来标识指示故障的数字。

HRESULT最初在IBM/Microsoft OS/2操作系统中作为一般目的的错误返回代码，并随后在Windows NT中使用。 Microsoft Visual Basic 的大幅度增加HRESULT错误报告机制，通过关联的一个 `IErrorInfo` 对象错误代码，通过存储指向一个`IErrorInfo`COM对象的线程本地存储。 `IErrorInfo`机制允许程序将各种信息与特定的HRESULT错误相关联：引发错误的对象的类，引发错误的对象的接口，错误文本; 以及帮助文件中帮助主题的链接。 此外，HRESULT错误的接收器可以根据需要获得错误消息的本地化文本。

随后，HRESULT和相关联的 `IErrorInfo` 机制用作COM中的默认错误报告机制。

在Windows中支持IErrorInfo机制是非常不一致的。 较旧的Windows API往往不支持它，返回HRESULTS没有任何 IErrorInfo 数据。 更多的现代Windows COM子系统通常会在IErrorInfo对象的消息描述中提供大量的错误信息。 IErrorInfo错误机制的更高级功能——帮助链接和按需定位，很少使用。

在.NET Framework中，从本机代码转换为托管代码时，HRESULT / `IErrorInfo`错误代码将转换为CLR异常; 当从托管转换为本机COM代码时，CLR异常将转换为HRESULT / IErrorInfo错误代码。

使用 HRESULT
----------

winerror.h文件定义了一些通用的HRESULT值。 有些HRESULT值被硬编码在给定子系统的关联头文件（.h文件）中。 这些值也使用Microsoft Windows平台SDK或DDK在相应的标题（.h）文件中定义。

要检查返回HRESULT的调用是否成功，请确保S字段为0（即数字为非负数）或使用`FAILED()`。要获取HRESULT的代码部分，请使用`HRESULT_CODE()`。您还可以使用名为ERR.EXE的工具获取值，并将其转换为相应的错误字符串。 另一个名为ERRLOOK.EXE的工具也可用于显示与给定HRESULT值相关联的错误字符串。 可以在Visual Studio命令提示符下运行ERRLOOK.EXE。

Windows 原生的 `SetErrorInfo` 和 `GetErrorInfo` API 用于将 HRESULT 返回码与对应的`IErrorInfo`对象相关联。

`FormatMessage` API函数可用于将一些非`IErrorInfo` HRESULT转换为用户可读的字符串。

示例
--

* `0x80070005`
	+ 8 - 错误
	+ 7 - Win32
	+ 5 - "E\_FAULT"
* `0x80090032`
	+ 8 - 错误
	+ 9 - SSPI
	+ 32 - "此请求不被支持"

引用
--

1. ↑  MSDN Windows Error Code reference （页面存档备份，存于）.
2. ↑   Win32 
错误代码

扩展链接
----

* Microsoft Open Protocol Specification - HRESULT Values（页面存档备份，存于）
* Microsoft Developer Network Reference（页面存档备份，存于）
* Windows Data Types（页面存档备份，存于）
* Using Macros for Error Handling（页面存档备份，存于）
* List of DOS, Windows and OS/2 error codes, 包括很多常用的HRESULT