如何改进COM接口?

时间:2009-10-25 13:33:38

标签: com winapi ole

众所周知,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;
        }
}

这是正确的方法吗?

我应该在Registry中添加一个Application10和Application20类来添加一个可能性来为脚本客户端实例化不同版本的应用程序吗?

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

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

我应该如何在不同版本的Windows注册表中注册coclass或接口?

请注意,我不使用ATL或WIN32-API以外的其他库。

如果您知道我在哪里可以找到相关信息(书籍,参考资料等),请提出建议。

我真的很感谢你的帮助。

1 个答案:

答案 0 :(得分:10)

是的,如果想要共存多个版本,则需要更改对象的class id。但是,您可以维护与program id类似的“Word.Application”或“InternetExplorer.Application”的版本无关redirects to the class id of the current version。向后兼容性很难维护。 MSXML显然放弃了与版本无关的progID的实践。

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

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

新接口的建议名称是interfact name加上版本号,例如IHtmlDocument6