COM采取通过返回HRESULT code的方式来获取COM调用的结果。但是往往返回的HRESULT非常抽象。为了使返回的Error information 更加具有可读性,COM支持ISupportErrorInfo interface来对Error information进行具体描述。
在COM service中返回一个具体的Error information过程如下所示:
参阅文章:http://msdn.microsoft.com/en-us/library/ms221062.aspx
在COM client 中检索error information的过程如下所示:

参阅文章:http://msdn.microsoft.com/en-us/library/ms221026.aspx
如何实现这种基于IErrorInfo的错误处理机制,可以参阅Microsoft Support KB:http://support.microsoft.com/kb/139073/en-us
下面的demo演示了通过ISupportErrorInfo interface, ICreateErrorInfo interface, IErrorInfo interface,以及CreateErrorInfo() API, SetErrorInfo() API和smart pointer来实现Error Handling .
COM service side:
=========
COM IDL File

Code
// ErrorDemo.idl : IDL source for ErrorDemo.dll
//
// This file will be processed by the MIDL tool to
// produce the type library (ErrorDemo.tlb) and marshalling code.
import "oaidl.idl";
import "ocidl.idl";
[
object,
uuid(6A5B3E68-A39C-4723-9EDD-E0795FCB8944),
dual,
helpstring("ISimpleClass Interface"),
pointer_default(unique)
]
interface ISimpleClass : IDispatch
{
[id(1), helpstring("method ErrorTest")] HRESULT ErrorTest([in]long errorSwitch,[out,retval]BSTR* result);
};
[
uuid(809E3C38-8D3A-4341-A76A-D3CA7DFCAC33),
version(1.0),
helpstring("ErrorDemo 1.0 Type Library")
]
library ERRORDEMOLib
{
importlib("stdole32.tlb");
importlib("stdole2.tlb");
[
uuid(B8E39F5E-3571-416B-A9A0-B45C1D22E3C0),
helpstring("SimpleClass Class")
]
coclass SimpleClass
{
[default] interface ISimpleClass;
};
};
SimpleClass Header File:

Code
// SimpleClass.h : Declaration of the CSimpleClass
#ifndef __SIMPLECLASS_H_
#define __SIMPLECLASS_H_
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// CSimpleClass
class ATL_NO_VTABLE CSimpleClass :
public CComObjectRootEx<CComSingleThreadModel>,
public CComCoClass<CSimpleClass, &CLSID_SimpleClass>,
public ISupportErrorInfo,
public IDispatchImpl<ISimpleClass, &IID_ISimpleClass, &LIBID_ERRORDEMOLib>
{
public:
CSimpleClass()
{
}
DECLARE_REGISTRY_RESOURCEID(IDR_SIMPLECLASS)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CSimpleClass)
COM_INTERFACE_ENTRY(ISimpleClass)
COM_INTERFACE_ENTRY(IDispatch)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
// ISimpleClass
public:
STDMETHOD(ErrorTest)(/*[in]*/long errorSwitch,/*[out,retval]*/BSTR* result);
};
#endif //__SIMPLECLASS_H_
SimpleClass Implementation:

Code
// SimpleClass.cpp : Implementation of CSimpleClass
#include "stdafx.h"
#include "ErrorDemo.h"
#include "SimpleClass.h"
/////////////////////////////////////////////////////////////////////////////
// CSimpleClass
// InterfaceSupportErrorInfo is implemented automatically
STDMETHODIMP CSimpleClass::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_ISimpleClass
};
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
//by myself
STDMETHODIMP CSimpleClass::ErrorTest(long errorSwitch, BSTR *result)
{
HRESULT hr=0;
if(errorSwitch)
{
CComPtr<ICreateErrorInfo> pCEI=NULL;
hr=::CreateErrorInfo(&pCEI);
if(FAILED(hr)) return hr;
pCEI->SetDescription(L"this is a error info demo");
pCEI->SetGUID(IID_ISimpleClass);
pCEI->SetSource(L"customized COM+");
CComPtr<IErrorInfo> pEI;
hr=pCEI.QueryInterface(&pEI);
if(FAILED(hr)) return hr;
::SetErrorInfo(0,pEI);
return E_FAIL;
}
else
*result=T2BSTR("Hello World, Error Demo");
return S_OK;
}
COM Client:
============
Client code:

Code
// ErrorDemoClient.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <comdef.h>
#include "..\ErrorDemo.h"
#include "..\ErrorDemo_i.c"
#include <atlbase.h>
int main(int argc, char* argv[])
{
CoInitialize(NULL);
CComPtr<ISimpleClass> pSP;
HRESULT hr=pSP.CoCreateInstance(__uuidof(SimpleClass));
if(FAILED(hr)) return hr;
BSTR result;
hr=pSP->ErrorTest(1,&result);
if(FAILED(hr))
{
CComPtr<ISupportErrorInfo> pSE=NULL;
pSP.QueryInterface(&pSE);
hr=pSE->InterfaceSupportsErrorInfo(IID_ISimpleClass);
if(SUCCEEDED(hr))
{
CComPtr<IErrorInfo> pEI=NULL;
hr=::GetErrorInfo(0,&pEI);
if(FAILED(hr)) return hr;
BSTR description;
GUID _guid;
pEI->GetDescription(&description);
pEI->GetGUID(&_guid);
_bstr_t t=description;
char* p=t;
printf("%s\n",p);
}
return hr;
}
_bstr_t t=result;
char* p=t;
printf("%s",p);
return 0;
CoUninitialize();
}
关于此demo的source code,点击此处下载