如何从CComDispatchDriver InvokeN调用的方法中获取HRESULT?
如何通过晚绑定COM调用获取原始HRESULT?
我通过晚绑定调用不同COM服务器的方法,代码如下:
HRESULT hr = drv.InvokeN(dispid, params.data(), static_cast<int>(params.size()), &retVal); if (!SUCCEEDED(hr)) {...}
当被调用方法返回自定义HRESULT时,InvokeN仅返回0x80020009(发生异常),无法直接获取到原始的HRESULT。
我已经尝试过两种方式,但都没能拿到原始HRESULT:
- 部分服务器实现了IErrorInfo接口,能获取错误描述,但无法获取对应的HRESULT:
IErrorInfo* pErrorInfo = nullptr; GetErrorInfo(0, &pErrorInfo); if (pErrorInfo != nullptr) { BSTR description; if (SUCCEEDED(pErrorInfo->GetDescription(&description))) { // 处理错误描述 SysFreeString(description); } pErrorInfo->Release(); }
- 调用
GetLastError(),但它始终返回0。
解决方案
要获取目标方法返回的原始HRESULT,推荐使用以下方式:
1. 直接调用IDispatch::Invoke方法
InvokeN是封装后的简化调用,会将目标方法的异常统一包装为0x80020009。而IDispatch::Invoke可以直接暴露原始错误信息:
DISPPARAMS dp = { params.data(), nullptr, static_cast<UINT>(params.size()), 0 }; EXCEPINFO excepInfo = { 0 }; UINT argErr = 0; HRESULT hr = drv->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dp, &retVal, &excepInfo, &argErr); if (FAILED(hr)) { // 若hr不是DISP_E_EXCEPTION,可能就是原始返回值 if (hr == DISP_E_EXCEPTION) { // 部分服务器会将原始HRESULT的低16位存入excepInfo.wCode if (excepInfo.wCode != 0) { HRESULT originalHr = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, excepInfo.wCode); // 处理原始错误码 } } else { // 直接使用hr作为原始错误码 } }
2. 从IErrorInfo扩展接口提取(依赖服务器实现)
少数COM服务器会将原始HRESULT存储在IErrorInfo的扩展属性中,你可以尝试查询服务器是否实现了ISupportErrorInfo或自定义错误接口,但这种方式不具备通用性,仅适用于特定服务器。
内容的提问来源于stack exchange,提问作者MiB_Coder
相关产品推荐
相关产品推荐

