ATL 结构在来自 dll 的 COM 对象上中断
Posted
技术标签:
【中文标题】ATL 结构在来自 dll 的 COM 对象上中断【英文标题】:ATL structures break on COM objects from dll 【发布时间】:2018-02-22 00:06:04 【问题描述】:因此,我们目前正在将一个古老的程序从 Visual Studio 2008(一切正常)升级到 2017。我们使用 dll,应用程序通过 ATL 和项目依赖项连接到其类。
不幸的是,所有从这些类调用函数的尝试都会返回异常,可能是因为它找不到它们。
构建时通过regedit成功将dll的类添加到注册表中,并且uuid与注册值正确对应。这些类也可以在 OLE/COM-viewer 中找到。
它也只会在尝试从我们的一个类中调用时中断。尝试从 IDispatch 调用函数(相关类继承自该函数)正常工作。
在下面的代码中,第一次尝试“m_pRenderer”会引发异常。第二次尝试“test2”没有进入它的 if 语句,因为 CoCreateInstance 返回一个错误的变量类型错误
HRESULT res = CoCreateInstance(__uuidof(CBSNullRenderer), NULL, CLSCTX_INPROC_SERVER, __uuidof(IDispatch), (void**)&m_pRenderer);
Log("\nCreateInstance: %ld", res);
ICBSNullRendererPtr test2 = NULL;
HRESULT res2 = CoCreateInstance(__uuidof(CBSNullRenderer), NULL, CLSCTX_INPROC_SERVER, __uuidof(ICBSNullRenderer), (void**)&test2);
Log("\nres2: %ld", res2);
wireHWND mainHwnd = (wireHWND)GetParent(p_hWnd);
if(mainHwnd == NULL)
Log("\nWARNING mainHWND is NULL!");
try
if (test2)
Log("\nDid create NullRenderer!");
test2->SetMainWnd(mainHwnd);
if (m_pRenderer)
Log("\nDid create NullRenderer!");
m_pRenderer->SetMainWnd(mainHwnd);
catch (...)
第 2 行的 m_pRenderer 中断:
inline HRESULT ICBSNullRenderer::SetMainWnd ( wireHWND hwnd )
HRESULT _hr = raw_SetMainWnd(hwnd);
if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
return _hr;
在 dll 的 .tli 文件中。
该错误会创建一个“抛出异常”对话框,其中包含以下内容:
在 0x00007FF9153ED7F2 (oleaut32.dll) 处抛出异常 AnimgramPro.exe: 0xC0000005: 访问冲突执行位置 0x00007FF9153ED7F2
我们还尝试将 m_pRenderer 上的 QueryInterface 与 nullrenderer 的 uuid 一起使用。这以另一个错误的变量类型错误结束。
任何可能相关的错误的建议或信息将不胜感激。
【问题讨论】:
CoCreateInstance()
的第一个参数应该是我们想要一个实例的 CoClass 的 CoClass ID (CLSID)。您似乎将您的接口ICBSNullRenderer
的接口ID (IID) 传递给它。难道没有像CCBSNullRendered
这样的CoClass 你想获得一个实例吗?
两次调用CoCreateInstance
的结果日志显示什么?
@KapilDhaimade 道歉,这是我写这个问题的一个错误。你的建议没有效果。
@RichardCritten 第一个返回 S_OK,第二个返回来自 winerr.h 的 DISP_E_BADVARTYPE。
HRESULT res = CoCreateInstance(..., __uuidof(IDispatch), (void**)&m_pRenderer);
这是非法的。您要求IDispatch*
指针,但您将它存储在IDispatch*
以外的类型的变量中。实际上,您检索IDispatch*
指针,然后将reinterpret_cast
检索到另一种类型。要么传递你想要的接口的实际IID
;或者将指针检索到 IDispatch*
变量中,然后将 QueryInterface
检索到您实际想要的接口。
【参考方案1】:
所以,我解决了这个问题。显然,在我的程序中正确调用 dll 函数需要关闭“公共语言运行时支持”并将“整个程序优化”设置为“使用链接时间码生成'
【讨论】:
以上是关于ATL 结构在来自 dll 的 COM 对象上中断的主要内容,如果未能解决你的问题,请参考以下文章
为 32 位 DLL 编写 COM/ATL Wrapper 的正确方式
OLEDB - C++ - ATL 的 OLEDB 提供程序示例使 Excel 崩溃(来自 msado15.dll 的未捕获异常)