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

时间:2011-03-04 08:26:15

标签: c++ com mfc activex

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

我已经完成了所有工作,但我知道我所做的就是臭!更新COM / ActiveX接口的正确方法是什么。

此组件是使用MFC构建的,除了基本的“使用MFC创建ActiveX控件”类型教程之外,Google搜索没有提供太多帮助。我可以找到关于ATL的大量内容,但我不想将组件移植过来。

我收到了各位同事提出的各种建议,例如更改guid并继承界面,但没有明确的确定。

一般来说,更新COM接口的最佳做法是什么?

如果您碰巧知道如何在MFC环境中专门完成此操作,那将非常有用。

我已经尝试按照MSalters的建议创建第二个界面(见下文),但我不确定我是否已正确使用它。我在odl文件中创建了一个新接口和一个新的coclass。这导致两个独立的包装类由MFC在客户端应用程序中生成,一个派生自CWnd for coclass Test,另一个派生自COleDispatchDriver for 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;
    };
};

2 个答案:

答案 0 :(得分:3)

取决于

如果您的客户正在根据控件的类型库,.h文件或.idl文件编译自己的代码(C ++或C#或VB),则可能需要更改COM指示。

以下是您无需更改COM指南的情况:

  1. 没有第三方开发人员在使用您的代码。如果更改界面,任何人都不会被打破。

  2. 它是一个托管在Web浏览器中的ActiveX控件,可通过Javascript访问。

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

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

  5. 如果上述任何一个属实,那么您不必更改COM guids。只需将新方法添加到现有接口声明中即可。使用更改重新编译所有相关软件。

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

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

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

    3. 在上面的例子中,我认为你不需要声明一个新的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;
      }
      

      };

答案 1 :(得分:1)

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