有趣的HRESULT

有趣的HRESULT

Author: ume Date: 2012-02-19

Outline:“Here’s Result”

HRESULTstructure

FAILED/SUCCEEDED

MAKE_HRESULT

FormatMessage

长时间进行Windows编程的人一定对HRESULT特别熟悉,因为HRESULT作为一种函数的返回值类型曝光率实在太高了,可是你是否知道HRESULT到底是什么?为什么不直接使用简洁又亲切的BOOL作为函数的返回值类型呢?

单从名字上看,HRESULT似乎是指向函数结果的句柄,但是这种直观地猜想却是错误的。其实HRESULT的意义非常简单,它不是Handle to Result而是Here’s the Result。怎么样?H竟然是Here的缩写,相当与众不同吧!

为了对HRESULT一探究竟,我们可以打开WinError.h文件,看一看它对HRESULT的描述:HRESULT是COM函数/方法的返回值类型,它并非指向什么东西的句柄,而仅仅是一个32位的数值。HRESULT的32位被划分成多个区域,其结构如下所示:(博主对它进行了简化)

3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1

1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 98 7 6 5 4 3 2 1 0

+-+-----------------------------+-------------------------------+

|S| Facility| Status |

+-+-----------------------------+-------------------------------+

HRESULT被划分成三个区域:紧急程度(S: 1 bit)、设备编号(Facility Code: 15 bit)和状态编号(Status Code: 16 bit)。这样一来你会发现,仅需1个bit(即S)就可以表示函数调用成功与否,余下的比特可以发挥更大的作用,它们携带的信息远比一个BOOL变量多得多,它们可以详细地说明函数调用过程中的各种情况,而不仅仅标明函数调用成功或失败。

观察HRESULT的结构之后,很容易明白下面这条规则:判断函数调用成功与否不能简单地将返回值与S_OK或E_NOINTERFACE等进行比较,而是要使用FAILED/SUCCEEDED宏。在WinError.h文件中,FAILED/SUCCEEDED宏的定义如下所示:

#define SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#define FAILED(hr) (((HRESULT)(hr)) < 0)

当然,你知道FAILED/SUCCEEDED宏的秘密后,也可以直接在程序中将hr与0进行大小判断。不过为了使得代码规范化,建议你仍然使用预定义宏FAILED/SUCCEEDED,而且他们并不会降低程序的效率。

光是会“读”HRESULT是不够的,有的时候我们还要能够主动创建它,从而使得我们定义的函数也能返回HRESULT类型的值。这可以通过使用预定义宏MAKE_HRESULT来实现,它在WinError.h文件的定义如下所示:

#defineMAKE_HRESULT(sev,fac,code) \

   ((HRESULT) (((unsigned long)(sev)<<31) | ((unsignedlong)(fac)<<16) | ((unsigned long)(code))))

在WinError.h文件中定义了很多错误码,能不能把函数的HRESULT类型返回值翻译成友好的错误提示呢?当然是可以的,我们可以通过调用Win32 API函数FormatMessage轻松实现,它的语法如下:

DWORDWINAPI FormatMessage(

  __in     DWORD dwFlags,

  __in_opt LPCVOID lpSource,

  __in     DWORD dwMessageId,

  __in     DWORD dwLanguageId,

  __out    LPTSTR lpBuffer,

  __in     DWORD nSize,

  __in_opt va_list* Arguments

);  

第1个参数dwFlags是格式化选项,如FORMAT_MESSAGE_ALLOCATE_BUFFER表示要为lpBuffer分配内存空间、FORMAT_MESSAGE_FROM_SYSTEM表示在系统消息定义表中查询错误码的意义;第2个参数lpSource表示临时的消息定义表,如果第1个参数包含FORMAT_MESSAGE_FROM_SYSTEM,lpSource就不起作用;第3个参数dwMessageId也就是错误码,传入LRESULT类型的数值;第4个参数dwLanguageId即语言标识符,它由两部分组成Primary Language(语言类型)和Sublanguage(国家或地区),用宏MAKELANGID构造;第5个参数lpBuffer是输出的消息,也即错误码的翻译结果;第6个参数nSize表示为lpBuffer最少分配的字节数;第7个参数可选,一般不使用。举一个应用的例子,如下所示:

void*pMsgBuf;

::FormatMessage(

        FORMAT_MESSAGE_ALLOCATE_BUFFER| FROMAT_MESSAGE_FROM_SYSTEM,

        NULL,

        hr,

        MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),

        (LPTSTR)&pMsgBuf,

        0,

        NULL);

读者不妨对应着上面的参数说明试着解释一下本例中各个实参的意义,更多细节可以参考MSDN的相关内容


03-28
<think>好的,我现在需要处理用户的问题,他们想了解“HREsUlt”。首先,我需要确认用户指的是什么,因为这个词看起来可能是拼写错误或者缩写。让我先拆解一下这个词。 “HREsUlt”可能由几个部分组成。HRE可能是一个常见的缩写,比如“Human Resources Executive”(人力资源主管),但后面接的“sUlt”不太常见。或者,HRE可能代表其他领域的概念,比如“High-Resolution Electrospray Ionization”(高分辨率电喷雾电离)在化学中,但加上“sUlt”还是不太清楚。 另一种可能是用户打错了,比如“HREsUlt”中的大小写混乱。例如,“HResult”是Windows编程中的一个常见术语,代表“HRESULT”,即一个用于表示操作成功或失败的错误代码。这可能是用户想了解的,尤其是如果他们涉及软件开发或系统错误排查的话。 考虑到用户可能输入错误,我需要检查常见的相关术语。HRESULT确实是系统级编程中的一个重要概念,特别是在COM(组件对象模型)和Win32 API中。它通常是一个32位的数值,用来表示成功、警告或错误。例如,S_OK表示成功,E_FAIL表示一般错误。 接下来,我需要验证这个可能性。如果用户确实指的是HRESULT,那么我需要准备一个结构化的解释,包括其定义、结构、常见值和使用场景。同时,按照用户的指示,使用中文回答,并且确保数学表达式或代码部分格式正确,比如用$...$包裹行内内容,独立公式用$$...$$。 另外,用户可能对如何解读和处理HRESULT错误代码感兴趣,尤其是在调试或处理COM对象时。需要说明如何分解HRESULT的各个部分,比如严重性位、保留位、设施代码和错误代码,以及如何使用工具如WinError.h头文件或在线资源查找具体错误含义。 还需要注意用户可能的背景,他们可能是开发者或IT支持人员,遇到系统错误需要理解HRESULT的含义。因此,回答需要技术准确,同时保持清晰易懂,提供实际例子会有帮助,比如常见的HRESULT值如E_ACCESSDENIED或E_OUTOFMEMORY。 最后,检查是否有其他可能的解释。比如,HREsUlt是否在某些特定领域或软件中有特殊含义?如果找不到其他合理的解释,应优先考虑HRESULT的可能性,并在回答中适当提及可能的拼写错误,以确保覆盖用户的需求。</think>您提到的“HREsUlt”可能是拼写错误或缩写。根据技术领域常见的术语推测,您可能想了解 **HRESULT**(正确拼写为全大写)。以下是关于HRESULT的详细介绍: --- ### 1. **HRESULT的定义** HRESULT是Windows系统中广泛使用的一种 **32位错误代码格式**,全称为 **Handle to a Result**。它主要用于COM(组件对象模型)编程、DirectX、Win32 API等场景,表示函数调用的成功、警告或错误状态。 --- ### 2. **HRESULT的结构** HRESULT的32位值按以下方式划分: - **第31位(最高位)**:严重性标识 - `0`:成功(SUCCESS) - `1`:失败(FAILURE) - **第30-29位**:保留位(通常为`00`) - **第28-16位**:**设施代码(Facility Code)**,标识错误来源(如操作系统、组件等)。例如: - `0x000`:FACILITY_NULL(通用错误) - `0x007`:FACILITY_WIN32(Win32 API错误) - **第15-0位**:**错误代码**,具体错误类型。 --- ### 3. **常见HRESULT值** | 值 | 名称 | 含义 | |--------------------|------------------|-----------------------------| | `0x00000000` | S_OK | 操作成功 | | `0x00000001` | S_FALSE | 操作成功但有条件未满足 | | `0x80004005` | E_FAIL | 未指明的错误 | | `0x80070005` | E_ACCESSDENIED | 访问被拒绝 | | `0x8007000E` | E_OUTOFMEMORY | 内存不足 | --- ### 4. **如何解析HRESULT?** - **编程中检查HRESULT**: 使用`SUCCEEDED(hr)`或`FAILED(hr)`宏判断操作是否成功。 ```cpp HRESULT hr = SomeFunction(); if (SUCCEEDED(hr)) { // 处理成功逻辑 } else { // 处理失败逻辑 } ``` - **查看具体错误信息**: 使用Windows SDK中的 `winerror.h` 头文件或在线工具(如[Microsoft Docs](https://docs.microsoft.com))查询错误代码。 --- ### 5. **实际应用场景** - **COM组件调用**:HRESULT用于跨进程或跨组件的错误传递。 - **DirectX图形编程**:如纹理加载失败时返回`E_INVALIDARG`。 - **系统API调用**:例如文件操作失败返回`HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)`。 --- ### 6. **注意事项** - **不要忽略HRESULT**:未处理的错误可能导致程序崩溃或数据丢失。 - **错误转换**:使用`HRESULT_FROM_WIN32()`将Win32错误码转换为HRESULT。 --- 如果您的“HREsUlt”指向其他领域的概念,请提供更多上下文,我将进一步补充说明!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值