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 的未捕获异常)

ATL COM DLL 寄存器错误 0x80070716

向 VBScript (ATL) 公开 COM 事件

ATL COM dll 中的缓冲区溢出

在 ATL COM dll 中调用了错误的方法