C++ 扩展现有ActiveX/COM组件的正确方法是什么?

C++ 扩展现有ActiveX/COM组件的正确方法是什么?,c++,com,mfc,activex,C++,Com,Mfc,Activex,我正在更新包含自定义ActiveX控件的MFC应用程序。作为更新的一部分,我有理由向ActiveX控件添加新方法,因此它现在与旧版本具有不同的接口。这些更改对原始方法没有影响,因此旧客户端仍然可以使用新组件 我什么都做得很好,但我知道我做的事很臭!更新COM/ActiveX接口的正确方法是什么 该组件是使用MFC构建的,除了基本的“使用MFC创建ActiveX控件”类型的教程外,Google并没有提供太多帮助。我可以找到大量关于ATL的内容,但我不想将组件移植到上面 我从同事那里得到了各种建议,

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

我什么都做得很好,但我知道我做的事很臭!更新COM/ActiveX接口的正确方法是什么

该组件是使用MFC构建的,除了基本的“使用MFC创建ActiveX控件”类型的教程外,Google并没有提供太多帮助。我可以找到大量关于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++技术来回收旧接口的大部分部分和实现。 如果您的客户正在根据控件的类型库、.h文件或.idl文件编译自己的代码(C++或C#或VB),则可能需要更改COM GUID

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

  • 没有第三方开发人员使用您的代码。如果你改变了界面,没有人会崩溃

  • 它是一个ActiveX控件,托管在webbrowser中,通过Javascript访问

  • 取决于COM DLL的所有软件随控件的更新版本一起提供

  • 这是“内部的”。任何依赖的人都可以在需要时快速重新编译

  • 如果上述任何一项为真,则不必更改COM GUID。只需将新方法添加到现有接口声明中。使用更改重新编译所有相关软件

    以下是你应该小心的情况

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

  • 您正在删除方法、更改行为或以其他方式对装运软件进行破坏性更改。更改CoClass上的guid,使其可能与依赖于旧版本的guid共存。同时重命名DLL,使其在升级时不必覆盖旧的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”方法。可能在新类或接口上。然后为这个“IMyControlVersion”接口共同创建实例和查询接口,并进行检测。