COM开发:从基础到企业级应用
立即解锁
发布时间: 2025-08-20 01:59:31 阅读量: 1 订阅数: 4 


COM+编程实战:使用Visual C++和ATL构建企业级应用
### COM 开发:从基础到企业级应用
#### 1. 错误报告优化
在实现 `ISVideo` 接口的 `GetSVideoSignalValue` 方法时,若成员变量超出限制,最初返回的是 SDK 定义的错误代码 `E_UNEXPECTED`。示例代码如下:
```cpp
// File Vcr.cpp
HRESULT CVcr::GetSVideoSignalValue(long* pRetVal)
{
if (m_nCurCount >= 5 || m_nCurCount < 0) {
return E_UNEXPECTED;
}
...
}
```
但这个错误代码对客户端和开发者来说信息不足,因为它可能由客户端和服务器之间的任何层产生。因此,使用自定义的 HRESULT 代码更有意义。可以在 IDL 文件中使用 `MAKE_HRESULT` 宏定义自定义 HRESULT,示例如下:
```cpp
// File Video.idl
cpp_quote("#define VCR_E_INTERNALERROR \
MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x200 + 1)")
```
修改 `GetSVideoSignalValue` 方法以返回新的 HRESULT 值:
```cpp
// File Vcr.cpp
HRESULT CVcr::GetSVideoSignalValue(long* pRetVal)
{
if (m_nCurCount >= 5 || m_nCurCount < 0) {
return VCR_E_INTERNALERROR;
}
...
}
```
客户端可以检查错误代码是否来自特定对象,示例代码如下:
```cpp
// File tv.cpp
int main(int /*argc*/, char* /*argv*/[])
{
::CoInitialize(NULL);
DoIt();
::CoUninitialize();
return 0;
}
void DoIt()
{
ISVideo* pSVideo = NULL;
HRESULT hr = ::CoCreateInstance(CLSID_VCR, NULL, CLSCTX_ALL,
IID_ISVideo, reinterpret_cast<void**>(&pSVideo));
if (FAILED(hr)) {
DumpError(hr);
return;
}
long val;
hr = pSVideo->GetSVideoSignalValue(&val);
if (SUCCEEDED(hr)) {
cout << "Value: " << val << endl;
return;
}
// The call failed
if (HRESULT_FACILITY(hr) == FACILITY_ITF) {
cout << "ISVideo specific error: 0x" << hex << hr << endl;
} else {
DumpError(hr);
}
}
```
自定义 HRESULT 不仅可以返回失败代码,还可以使用 `SEVERITY_SUCCESS` 返回成功代码。
#### 2. 智能指针的使用
在 TV 客户端代码中,存在忘记调用 `Release` 释放 `pSVideo` 接口指针的问题。为了解决这个问题,可以使用 ATL 提供的 `CComPtr` 模板。修改后的代码如下:
```cpp
// File tv.cpp
...
#include <atlbase.h>
...
void DoIt()
{
CComPtr<ISVideo> spSVideo;
HRESULT hr = ::CoCreateInstance(CLSID_VCR, NULL, CLSCTX_ALL,
IID_ISVideo, reinterpret_cast<void**>(&spSVideo));
if (FAILED(hr)) {
DumpError(hr);
return;
}
long val;
hr = spSVideo->GetSVideoSignalValue(&val);
if (SUCCEEDED(hr)) {
cout << "Value: " << val << endl;
return;
}
// The call failed
if (HRESULT_FACILITY(hr) == FACILITY_ITF) {
cout << "ISVideo specific error: 0x" << hex << hr << endl;
} else {
DumpError(hr);
}
}
```
`spSVideo` 变量在超出作用域时,如果不为 NULL,会自动释放自身。
Visual C++ 原生支持一个类似功能的智能指针类 `_com_ptr_t`,可以使用 `_COM_SMARTPTR_TYPEDEF` 宏创建接口的专用版本,示例如下:
```cpp
_COM_SMARTPTR_TYPEDEF(ISVideo, __uuidof(ISVideo));
```
#### 3. 提供更详细的错误信息
自定义 HRESULT 本身对客户端来说仍然不够描述性,COM 定义了 `IErrorInfo` 接口,服务器可以使用该接口设置扩展错误信息,客户端可以使用该接口检索信息。`IErrorInfo` 接口将扩展错误信息分为五个字段:
| 字段 | 说明 |
| ---- | ---- |
| 接口的 IID | 设置错误信息的接口的 IID |
| 错误信息源 | 通常填充对象的类名 |
| 错误的文本描述 | 对错误的详细描述 |
| Windows 帮助文件名 | 记录此错误的 Windows 帮助文件名(如果有) |
| Windows 帮助
0
0
复制全文
相关推荐










