【问题标题】:What is the correct way to extend an existing ActiveX/COM component?扩展现有 ActiveX/COM 组件的正确方法是什么?
【发布时间】:2011-07-08 15:49:00
【问题描述】:

我正在更新一个包含自定义 ActiveX 控件的 MFC 应用程序。作为更新的一部分,我有理由向 ActiveX 控件添加新方法,因此它现在具有与旧版本不同的界面。这些更改对原始方法没有影响,因此老客户仍然可以使用新组件。

我一切正常,但我知道我所做的很臭!更新 COM/ActiveX 接口的正确方法是什么。

这个组件是使用 MFC 构建的,除了基本的“使用 MFC 创建 ActiveX 控件”类型的教程之外,谷歌搜索并没有提供太多帮助。我可以找到很多关于 ATL 的资料,但我不想移植该组件。

我从同事那里得到了各种建议,例如更改 guid 和继承界面,但没有确定的。

那么一般来说,更新 COM 接口的最佳实践是什么?

如果您碰巧知道这是如何在 MFC 环境中专门完成的,那也会很有帮助。

我已尝试按照 MSalters 的建议创建第二个界面(见下文),但我不确定我是否正确地进行了操作。我在 odl 文件中创建了一个新接口和一个新的 coclass。这导致 MFC 在客户端应用程序中生成两个单独的包装类,一个派生自 CWnd 用于 coclass Test,一个派生自 COleDispatchDriver 用于 coclass Test2 - 我本来希望有两个类似的包装类....

library TestLib
{
    importlib(STDOLE_TLB);

    // This is the original interface.......

    [ uuid(D2F8E5A8-8A95-463C-814F-B3CF84286223)]
    dispinterface _DTest
    {
        properties:
        methods:
            [id(1)] short TestMethod();
    };

    //  Class information for CTestCtrl
    [ uuid(1DBD2333-2073-4FB6-89AC-E4B200ADED48), control ]
    coclass Test
    {
        [default] dispinterface _DTest;
    };


    //  This is the new interface.

    [ uuid(D2F8E5A8-8A95-463C-814F-B3CF84286224)]
    dispinterface _DTest2
    {
        properties:
        methods:
            [id(1)] short TestMethod();
            [id(2)] short TestMethod2();
    };

    //  Class information for CTestCtrl2

    [ uuid(1DBD2333-2073-4FB6-89AC-E4B200ADED49), control ]
    coclass Test2
    {
        [default] dispinterface _DTest2;
    };
};

【问题讨论】:

    标签: c++ com mfc activex


    【解决方案1】:

    视情况而定。

    如果您确实有客户根据控件的类型库、.h 文件或 .idl 文件编译自己的代码(C++ 或 C# 或 VB),您可能需要更改 COM guid。

    以下是您不必更改 COM guid 的情况:

    1. 没有第 3 方开发人员正在使用您的代码。换个界面就不会坏人了。

    2. 它是托管在网络浏览器中并通过 Javascript 访问的 ActiveX 控件。

    3. 取决于您的 COM DLL 的所有软件都与您的控件的更新版本一起提供。

    4. 它是“内部的”。如果需要,任何依赖的人都可以快速重新编译。

    如果以上任何一项为真,那么您不必更改 COM guid。只需将新方法添加到现有接口声明中即可。使用更改重新编译所有依赖软件。

    以下是你应该小心的情况。

    1. 其他人已经根据您现有的界面编译(C++、C# 或 VB)并发布了软件 - 他们无法在您发布时立即升级。应该在新的 COM 接口上声明新方法。现有的 coclass 声明也经过修改以支持此接口。

    2. 您正在删除方法、更改行为或以其他方式对交付软件进行重大更改。更改 CoClass 上的 guid,使其可能与依赖旧版本的那些并存。重命名 DLL,使其在升级时不必覆盖旧的。

    在你上面的例子中,我认为你不需要声明一个新的 coclass - 只是一个新的接口。而且你的新接口不需要实现第一个方法。只需在 coclass 上标记两个接口即可。

    dispinterface _DTest
    {
        properties:
        methods:
            [id(1)] short TestMethod();
    };
    
    //  This is the new interface.
    [ uuid(D2F8E5A8-8A95-463C-814F-B3CF84286224)]
    dispinterface _DTest2
    {
        properties:
        methods:
            [id(2)] short TestMethod2();
    };
    
    
    //  Class information for CTestCtrl
    [ uuid(1DBD2333-2073-4FB6-89AC-E4B200ADED48), control ]
    coclass Test
    {
        [default] dispinterface _DTest;
        dispinterface _DTest2;
    }
    

    };

    【讨论】:

    • 感谢简洁明了的回答!需要澄清的一件小事 - 他们在运行时是否有任何方法来检查新组件或旧组件是否已注册?我正在考虑增加组件的版本,然后检查注册表.....
    • 最简单的事情就是向您的 IDL 添加一个“GetVersion”方法。可能在新的类或接口上。然后 CoCreateInstance 和 QueryInterface 为这个“IMyControlVersion”接口做你的检测。
    【解决方案2】:

    您始终可以添加接口。新控件可以简单地同时实现新旧接口。继承是一种简单的 C++ 技术,可以回收大部分旧接口和实现。

    【讨论】:

    • 我已经尝试过了,但我不确定我做的是否正确 - 请参阅已编辑的问题。
    猜你喜欢
    • 2022-12-04
    • 1970-01-01
    • 1970-01-01
    • 2020-08-18
    • 1970-01-01
    • 2020-02-13
    • 2017-09-14
    • 1970-01-01
    • 2018-05-07
    相关资源
    最近更新 更多