开发者

How to evolve a COM interface?

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>

[开发者_如何学C
    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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜