COM组件设计与应用(十二)
错误与异常处理
作者:杨老师
下载源代码
一、前言
程序设计中,错误处理必不可少,而且通常要占用很大的篇幅。本回书着落在 COM 中的错误(异常)的处理方法。
在组件程序中,如果遇到错误,一般有两个方式进行处理。
二、简单返回
对于比较简单的错误,直接返回表示错误原因的 HRESULT。比如下面几个就是常见的错误值:
E_INVALIDARG | 0x80070057 | 参数错误 |
E_OUTOFMEMORY | 0x8007000E | 内存错误 |
E_NOTIMPL | 0x80004001 | 未实现 |
E_POINTER | 0x80004003 | 无效指针 |
E_HANDLE | 0x80070006 | 无效句柄 |
E_ABORT | 0x80004004 | 终止操作 |
E_ACCESSDENIED | 0x80070005 | 拒绝访问 |
E_NOINTERFACE | 0x80004002 | 不支持接口 |
另外,你还可以返回自己构造 HRESULT 错误值。方法是使用宏 MAKE_HRESULT(sev,fac,code)
参数 | 含义 | 值(二进制) |
sev 严重程度 | 成功 | 00 |
成功,但有一些报告信息 | 01 | |
警告 | 10 | |
错误 | 11 | |
fac 设备信息 | FACILITY_AAF | 00000010010 |
FACILITY_ACS | 00000010100 | |
FACILITY_BACKGROUNDCOPY | 00000100000 | |
FACILITY_CERT | 00000001011 | |
FACILITY_COMPLUS | 00000010001 | |
FACILITY_CONFIGURATION | 00000100001 | |
FACILITY_CONTROL | 00000001010 | |
FACILITY_DISPATCH | 00000000010 | |
FACILITY_DPLAY | 00000010101 | |
FACILITY_HTTP | 00000011001 | |
FACILITY_INTERNET | 00000001100 | |
FACILITY_ITF | 00000000100 | |
FACILITY_MEDIASERVER | 00000001101 | |
FACILITY_MSMQ | 00000001110 | |
FACILITY_NULL | 00000000000 | |
FACILITY_RPC | 00000000001 | |
FACILITY_SCARD | 00000010000 | |
FACILITY_SECURITY | 00000001001 | |
FACILITY_SETUPAPI | 00000001111 | |
FACILITY_SSPI | 00000001001 | |
FACILITY_STORAGE | 00000000011 | |
FACILITY_SXS | 00000010111 | |
FACILITY_UMI | 00000010110 | |
FACILITY_URT | 00000010011 | |
FACILITY_WIN32 | 00000000111 | |
FACILITY_WINDOWS | 00000001000 | |
FACILITY_WINDOWS_CE | 00000011000 | |
code 唯一错误码 | 16位(bit) 你自己定义去吧 |
调用者得到返回的 HRESULT 值后,也可以使用宏 HRESULT_SEVERITY()、HRESULT_FACILITY()、HRESULT_CODE() 来取得sev错误程度、fac设备信息和 code 错误代码。
三、错误信息接口
既然 COM 是靠各种各样的接口来提供服务的,于是很自然地就会想到,是否有一个接口能够提供更丰富的错误信息报告那?答案是:ISupportErrorInfo。下面这段代码是使用 ISupportErrorInfo 的一般方法:
学习了 C++ 后,很多人都喜欢使用 try/catch 的异常处理结构。如果你使用 vc6.0 的ATL,编译器默认是不支持异常处理的,编译后会报告“warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify -GX”,解决方法是手工加上编译开关:
![comtut12pic1.jpg](https://i-blog.csdnimg.cn/blog_migrate/b376d755818fcbaaf721cc585a3102e9.png)
图一、加上编译开关,支持C++的异常处理结构
在vc.net 2003 中,编译器默认是支持异常处理结构的,所以不用特别进行设置。如果想减小目标文件的尺寸,你也可以决定不使用 C++ 异常处理,那么在项目属性中
![comtut12pic2.jpg](https://i-blog.csdnimg.cn/blog_migrate/7d253f530154e02c74afdf15d36f311a.png)
图二、在vc.net中修改是否支持C++异常结构的编译开关
五、客户端接收组件的错误信息
1、如果使用 API 方式调用组件,接收错误的方法是: 2、如果使用 #import 等包装方式调用组件,接收错误的方法是: 六、编写支持错误处理的组件程序
非常简单,只要在增加 ATL 组件对象的时候选中 ISupportErrorInfo 即可。
![comtut12pic3.jpg](https://i-blog.csdnimg.cn/blog_migrate/f9c5e07556b855f9b03f9ee45df1044a.png)
图三、vc6.0 中,选中组件支持错误处理接口
![comtut12pic4.jpg](https://i-blog.csdnimg.cn/blog_migrate/27abe56cea85bf30bc9c8f886604bd26.png)
图四、vc.net 2003 中,选中组件支持错误处理接口
七、小结
阅读文章后,请下载本回的示例程序。示例程序中演示了三种错误处理方法和三种接收错误的方法,同时程序中也有比较详细的注释。