0

我最近继承了一个在 DLL 中创建和实现 COM coclass/interface 的项目。该 COM DLL 由应用程序使用,该应用程序将 GUI 应用于 COM 类的接口。这是唯一使用 COM DLL 的应用程序。我是处理 COM 的新手,很难找到好的文档。

我的部分任务涉及向接口添加一些方法/属性(以及删除一些不再需要的)。我了解到我需要修改 IDL 才能完成此操作。现在我只是简单地将我的新方法和属性添加到接口的末尾,一切似乎都很好。但是,当我删除其中一个属性(例如)时,当我运行应用程序时,事情很快就会变糟。

interface IMyComInterface : IDispatch
    {
        [id(1), helpstring("method CheckMessage")] HRESULT CheckMessage([in] VARIANT vMsg);
        [id(2), helpstring("method CheckFolder")] HRESULT CheckFolder([in] VARIANT Folder, [out] VARIANT *pCount, [out, retval] VARIANT *pErrorCount);
        //[propget, id(3), helpstring("property Flags")] HRESULT Flags([out, retval] VARIANT *pVal);
        //[propput, id(3), helpstring("property Flags")] HRESULT Flags([in] VARIANT newVal);
        [propget, id(4), helpstring("property MessageStore")] HRESULT MessageStore([out, retval] VARIANT *pVal);
        [propput, id(4), helpstring("property MessageStore")] HRESULT MessageStore([in] VARIANT newVal);
        [propget, id(5), helpstring("property Directory")] HRESULT Directory([out, retval] VARIANT *pVal);
        [propput, id(5), helpstring("property Directory")] HRESULT Directory([in] VARIANT newVal);
    }

我猜这与分解的身份证号码序列有关。我想我可以把它下面的所有东西都移上来,一切都会奏效。但我很好奇做这一切的正确方法。

非常感谢。

4

2 回答 2

2

如果 GUI 用于IDispatch::Invoke调用您的方法,它应该能够适应接口中的更改(只要您保持 ID 相同),因为方法调用是在运行时解决的(后期绑定)。VB6 程序和脚本语言以这种方式运行是很常见的。

但是,如果 GUI 是直接编译的IMyComInterface(如果它是 C++ 或 C# 应用程序最有可能),那么重要的是接口中方法的确切顺序。方法调用在编译时解析(早期绑定),接口中方法的索引存储在COM客户端中。如果您从 IDL 中删除一个方法,来自客户端的所有函数调用都将关闭一个。这就是为什么在最后添加新方法有效,但在中间删除方法无效。

解决所有这些问题的最简单方法(因为您同时控制 COM DLL 和 GUI)是确保在更改 IDL 后重新编译所有内容。但是,在一般情况下,您应该将每个接口视为“一组方法的不可变契约”(source),并且在 COM 接口发布后永远不要修改它。

于 2013-02-19T04:19:39.657 回答
1

如果 COM 客户端是 C++,它可能会使用早期绑定(这意味着它依赖于保持不变的界面布局)而不是后期绑定。在这种情况下,DISPID 是什么并不重要,因为 DISPID 用于后期绑定,而不是用于早期绑定。这就是为什么从接口中删除方法/属性会破坏客户端,除非你重新编译它。这也是为什么不建议更改 COM 接口,而是添加从旧接口继承的新接口并添加新功能的原因:

interface IMyComInterface : IDispatch
{
    // existing methods/properties
}

interface IMyComInterface2 : IMyComInterface
{
    // new methods/properties
}
于 2013-02-19T04:22:28.820 回答