扩展现有 ActiveX/COM 组件的正确方法是什么?
我正在更新包含自定义 ActiveX 控件的 MFC 应用程序。作为更新的一部分,我有理由向 ActiveX 控件添加新方法,因此它现在具有与旧版本不同的界面。这些更改对原始方法没有影响,因此旧客户端仍然可以使用新组件。
我已经把一切都做好了,但我知道我所做的很臭!更新 COM/ActiveX 接口的正确方法是什么?
该组件是使用 MFC 构建的,除了基本的“使用 MFC 创建 ActiveX 控件”类型教程外,谷歌搜索并没有提供太多帮助。我可以找到大量有关 ATL 的内容,但我不想移植该组件。
我从同事那里得到了各种建议,例如更改指南和继承界面,但没有任何明确的建议。
那么一般来说更新 COM 接口的最佳实践是什么?
如果您碰巧知道这是如何在 MFC 环境中具体完成的,那也会非常有帮助。
我已经尝试按照 MSalters 的建议创建第二个界面(见下文),但我不确定我是否正确地进行了操作。我在 odl 文件中创建了一个新的接口和一个新的组件类。这导致 MFC 在客户端应用程序中生成两个单独的包装类,一个派生自用于 coclass Test 的 CWnd,一个派生于用于 coclass Test2 的 COleDispatchDriver - 我本来期望有两个类似的包装类......
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;
};
};
I am updating an MFC application that contains a custom ActiveX control. As a part of the update I have had cause to add new methods to the ActiveX control and so it now has a different interface to the old version. The changes had no impact on the original methods and so older clients can still use the new component.
I've got everything working but I know that what I have done is smelly! What is the correct way of updating a COM/ActiveX interface.
This component was built using MFC and Googling does not provide much help beyond basic 'Create an ActiveX control with MFC' type tutorials. I can find loads of stuff about ATL but I don't want to port the component over.
I have had various suggestions from colleagues such as change the guids and inherit the interface but nothing definitive.
So generally what is considered best practise for updating COM interfaces?
And if you happen to know how this is specifically done in an MFC environment that would be really helpful too.
I've tried creating a second interface (see below) as suggested by MSalters but I'm not sure that I've gone about it correctly. I've created a new interface and a new coclass in the odl file. This results in two separate wrapper classes being generated by MFC in the client Application, one derived from CWnd for coclass Test and one derived from COleDispatchDriver for coclass Test2 - I would have expected two similar wrapper classes....
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;
};
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
视情况而定。
如果您确实有客户针对控件的类型库、.h 文件或 .idl 文件编译自己的代码(C++ 或 C# 或 VB),则您可能需要更改 COM guid。
以下是您不必更改 COM guid 的情况:
没有第 3 方开发人员正在使用您的代码。如果您更改了界面,没有人会受到影响。
它是一个托管在网络浏览器中并通过 Javascript 访问的 ActiveX 控件。
所有依赖于您的 COM DLL 的软件都与您的控件的更新版本一起提供。
这是“内部”。如果需要,任何依赖者都可以快速重新编译。
如果上述任何一项为真,那么您不必更改 COM guid。只需将新方法添加到现有的接口声明中即可。重新编译所有相关软件进行更改。
以下是您应该小心的情况。
其他人已经根据您现有的接口编译(C++、C# 或 VB)并发布了软件 - 并且他们无法在您发布时立即升级。新方法应在新的 COM 接口上声明。现有的组件类声明也经过修改以支持此接口。
您正在删除方法、更改行为或以其他方式对交付软件进行重大更改。更改 CoClass 上的 guid,以便它可以与依赖于旧版本的 guid 并存。还要重命名 DLL,以便它在升级时不一定会覆盖旧的。
在上面的示例中,我认为您不需要声明一个新的组件类 - 只需声明一个新接口。并且您的新接口不需要实现第一个接口的方法。只需在组件类上标记两个接口即可。
};
Depends.
If you do have customers that are compiling their own code (C++ or C# or VB) against your controls's type library, .h file, or .idl file, you likely need to change the COM guids.
Here are the cases where you don't have to change the COM guids:
No 3rd party developers are consuming your code. No one would be broken if you changed the interface.
It's an ActiveX control hosted in a webbrowser and accessed through Javascript.
All the software depending on your COM DLL ships together with the updated version of your control.
It's "internal". Anyone dependent can quickly recompile if needed.
If any one of the above is true, then you don't have to change COM guids. Just add the new methods to the existing interface declaration. Recompile all dependent software with the change.
Here are the cases where you should be careful.
Someone else has already compiled (C++, C#, or VB) and shipped software against your existing interface - and they can't immediately upgrade when you ship. New methods should be declared on a new COM interface. The existing coclass declaration gets amended to support this interface as well.
You are removing methods, changing behavior, or otherwise making a breaking change to shipping software. Change your guid on the CoClass such that it can possibly co-exist side by side with those dependent on the old version. Rename the DLL as well such that it doesn't necessarily overwrite the old one on upgrade.
In your above example, I don't think you need to declare a new coclass - just a new interface. And your new interface doesn't need to implement the methods of the first. Just make mark both interfaces on the coclass.
};
您可以随时添加接口。新控件可以简单地同时实现新旧接口。继承是一种简单的 C++ 技术,可以回收大部分旧接口和实现。
You can always add interfaces. The new control can simply implement the old and new interfaces at the same time. Inheritance is an easy C++ technique to recycle large parts of the old interface and implementation.