如何演化COM接口?

发布于 2024-08-08 19:19:24 字数 4464 浏览 7 评论 0原文

众所周知,COM 在发布新组件或应用程序时可以实现向后兼容。这是可能的,因为 COM 中的接口是稳定的,即它们不会改变。

我努力寻找参考资料或书籍来描述如何将 COM 接口从一个版本演变到另一个版本。

以下是我的要求:

我们有一个可以由 ole 自动化驱动的应用程序。该应用程序的新版本可以与旧版本并行安装。

此应用程序的 COM 客户端可以使用版本无关的 PROGID(在这种情况下,它们使用应用程序的最新版本)或版本相关的 PROGID(在这种情况下,它们使用应用程序的特定版本)。

对 COM 自动化的更改不应破坏任何客户端。

让我们看一个例子:

#include <olectl.h>
#include <fxbase\autoif.h>

[
    uuid(A1B3A66F-806F-46a2-82D9-9C278F415148),
    lcid(-1),
    version(1.0)
]

library LIB
{   
        importlib("stdole2.tlb");

        [
            uuid(82CDE055-790A-4505-BF3E-3282170C8FC6),
            helpstring("Document"),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IDocument : IDispatch
        {
                [id(0x00000001), propget, helpcontext(0x0012c94a)]
                HRESULT Name([out, retval] BSTR* psName);

                [id(0x00000001), propput, helpcontext(0x0012c94a)]
                HRESULT Name([in] BSTR psName);
        }

        [
            uuid(919B9E6E-76C0-4c23-A188-5840E5900997),
            helpstring("Application object."),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IApplication : IDispatch
        {
            [id(0x00000001), propget, helpstring("Returns the active document of the application.")]
            HRESULT ActiveDocument([out, retval] IDocument** retval);
        }

        [
            uuid(E0AA6FCA-AEF1-460b-A1F9-26250C28594B),
            helpstring("Application 1.0 Class"),
            appobject
        ]
        coclass Application
        {
            [default] interface IApplication;
                                interface IDispatch;
        }
}

假设我想发布这个应用程序的 2.0 版本,它扩展了一些接口。这是我对 2.0 版本的幼稚方法:

#include <olectl.h>
#include <fxbase\autoif.h>

[
    uuid(3D4688A2-91F8-4cd8-989A-845810A05557),
    lcid(-1),
    version(2.0)
]

library LIB
{   
        importlib("stdole2.tlb");

        [
            uuid(82CDE055-790A-4505-BF3E-3282170C8FC6),
            helpstring("Document"),
            oleautomation,
            dual
        ]
        interface IDocument10 : IDispatch
        {
                [id(0x00000001), propget, helpcontext(0x0012c94a)]
                HRESULT Name([out, retval] BSTR* psName);

                [id(0x00000001), propput, helpcontext(0x0012c94a)]
                HRESULT Name([in] BSTR psName);
        }

        [
            uuid(AF404510-216A-407e-99F4-0636AF071B68),
            helpstring("Document"),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IDocument : IDocument10
        {
                [id(0x00000001), propget, helpcontext(0x0012c94a)]
                HRESULT Type([out, retval] BSTR* psType);

                [id(0x00000001), propput, helpcontext(0x0012c94a)]
                HRESULT Type([in] BSTR psType);
        }

        [
            uuid(919B9E6E-76C0-4c23-A188-5840E5900997),
            helpstring("Application object."),
            oleautomation,
            dual
        ]
        interface IApplication10 : IDispatch
        {
            [id(0x00000001), propget, helpstring("Returns the active document of the application.")]
            HRESULT ActiveDocument([out, retval] IDocument** retval);
        }

        [
            uuid(6A851C3F-21DF-4f5e-A4D6-2EF5A9D234C6),
            helpstring("Application object."),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IApplication : IApplication10
        {
            [id(0x00000002), propget, helpstring("Is the application visible.")]
            HRESULT Visible([out, retval] BOOL* retval);
        }

        [
            uuid(AA760349-1682-4ab6-BF0C-C02E620715CF),
            helpstring("Application 2.0 Class"),
            appobject
        ]
        coclass Application
        {
            [default] interface IApplication;
                                interface IDispatch;
        }
}

这是执行此操作的正确方法吗?

我是否应该将类 Application10 和 Application20 添加到注册表中,以添加为脚本客户端实例化不同版本的应用程序的可能性?

更改类型库的版本 GUID 是否正确?

2.0 版中的 IDocument 有一个新的 IID。我仍然可以在 IApplication.ActiveDocument 中使用 IDocument 吗?

不同版本的Windows注册表中应该如何注册组件类或接口?

请注意,除了 WIN32-API 之外,我不使用 ATL 或其他库。

如果您知道在哪里可以找到这方面的信息(书籍、参考资料等),请推荐一本。

我非常感谢你的帮助。

COM is known to make backward-compatibility possible when releasing new components or applications. This is possible because interfaces in COM are stable i.e. they do not change.

I tried hard to find a reference or book which deals with a descrition on how to evole a COM interface from version to version.

The following are my requirements:

We have an application which can be driven by ole automation. New versions of this application can be installed in parrallel to older versions.

COM clients of this applications can use the version independent PROGID in which case they work with the latest version of the application or a version dependent PROGID in which case they work with the specific version of the application.

Changes to the COM automation should not break any of the clients.

Lets see an example:

#include <olectl.h>
#include <fxbase\autoif.h>

[
    uuid(A1B3A66F-806F-46a2-82D9-9C278F415148),
    lcid(-1),
    version(1.0)
]

library LIB
{   
        importlib("stdole2.tlb");

        [
            uuid(82CDE055-790A-4505-BF3E-3282170C8FC6),
            helpstring("Document"),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IDocument : IDispatch
        {
                [id(0x00000001), propget, helpcontext(0x0012c94a)]
                HRESULT Name([out, retval] BSTR* psName);

                [id(0x00000001), propput, helpcontext(0x0012c94a)]
                HRESULT Name([in] BSTR psName);
        }

        [
            uuid(919B9E6E-76C0-4c23-A188-5840E5900997),
            helpstring("Application object."),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IApplication : IDispatch
        {
            [id(0x00000001), propget, helpstring("Returns the active document of the application.")]
            HRESULT ActiveDocument([out, retval] IDocument** retval);
        }

        [
            uuid(E0AA6FCA-AEF1-460b-A1F9-26250C28594B),
            helpstring("Application 1.0 Class"),
            appobject
        ]
        coclass Application
        {
            [default] interface IApplication;
                                interface IDispatch;
        }
}

Lets say I want to publish version 2.0 of this application which extends some interfaces. Here is my naive approach to version 2.0:

#include <olectl.h>
#include <fxbase\autoif.h>

[
    uuid(3D4688A2-91F8-4cd8-989A-845810A05557),
    lcid(-1),
    version(2.0)
]

library LIB
{   
        importlib("stdole2.tlb");

        [
            uuid(82CDE055-790A-4505-BF3E-3282170C8FC6),
            helpstring("Document"),
            oleautomation,
            dual
        ]
        interface IDocument10 : IDispatch
        {
                [id(0x00000001), propget, helpcontext(0x0012c94a)]
                HRESULT Name([out, retval] BSTR* psName);

                [id(0x00000001), propput, helpcontext(0x0012c94a)]
                HRESULT Name([in] BSTR psName);
        }

        [
            uuid(AF404510-216A-407e-99F4-0636AF071B68),
            helpstring("Document"),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IDocument : IDocument10
        {
                [id(0x00000001), propget, helpcontext(0x0012c94a)]
                HRESULT Type([out, retval] BSTR* psType);

                [id(0x00000001), propput, helpcontext(0x0012c94a)]
                HRESULT Type([in] BSTR psType);
        }

        [
            uuid(919B9E6E-76C0-4c23-A188-5840E5900997),
            helpstring("Application object."),
            oleautomation,
            dual
        ]
        interface IApplication10 : IDispatch
        {
            [id(0x00000001), propget, helpstring("Returns the active document of the application.")]
            HRESULT ActiveDocument([out, retval] IDocument** retval);
        }

        [
            uuid(6A851C3F-21DF-4f5e-A4D6-2EF5A9D234C6),
            helpstring("Application object."),
            oleautomation,
            dual,
            nonextensible
        ]
        interface IApplication : IApplication10
        {
            [id(0x00000002), propget, helpstring("Is the application visible.")]
            HRESULT Visible([out, retval] BOOL* retval);
        }

        [
            uuid(AA760349-1682-4ab6-BF0C-C02E620715CF),
            helpstring("Application 2.0 Class"),
            appobject
        ]
        coclass Application
        {
            [default] interface IApplication;
                                interface IDispatch;
        }
}

Is this the correct way to do this?

Should I add a class Application10 and Application20 to the Registry to add a possiblitity to instantiate the different versions of the application for script clients?

Is it right to change the version and the GUID of the type library?

IDocument in version 2.0 has a new IID. Can I still use IDocument in IApplication.ActiveDocument?

How should I register the coclass or interface in the Windows Registry in the different versions?

Please note that I do not use ATL or other libraries other than the WIN32-API.

If you know where can I find information on this (books, references, etc.) please suggest one.

I would really appreciate your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

奈何桥上唱咆哮 2024-08-15 19:19:24

是的,您需要更改类 ID如果想要多个版本共存,请使用您的对象。不过,您可以维护与版本无关的程序 ID 就像“Word.Application”或“InternetExplorer.Application”重定向到当前版本的类ID。向后兼容性很难维护。 MSXML 显然放弃了版本无关的 progID 的做法。

如果您决定保留旧接口(推荐),则需要在新对象中同时实现新接口和旧接口。

您可能需要检查 Microsoft Office 的注册表整体。它很好地保持了向后兼容性。

新接口的建议名称为接口名称加版本号,例如 IHtmlDocument6

Yes, you need to change the class id of your object if want multiple versions to coexist. However you can maintain a version-independent program id like "Word.Application" or "InternetExplorer.Application" that redirects to the class id of the current version. Backward compatibility is very hard to maintain. MSXML apparently gave up the practice of version-independent progID .

If you decide to keep old interfaces (recommended), you need to implement both new and old interfaces in your new object.

You may want to check Microsoft Office's registry entires. It maintains backward compatibility quite well.

Suggested name of new interfaces would be interfact name plus version number, such as IHtmlDocument6.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文