Как развивать интерфейс COM? - PullRequest
8 голосов
/ 25 октября 2009

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 библиотеки типов?

IDocument в версии 2.0 имеет новый IID. Могу ли я по-прежнему использовать IDocument в IApplication.ActiveDocument?

Как мне зарегистрировать coclass или интерфейс в реестре Windows в разных версиях?

Обратите внимание, что я не использую ATL или другие библиотеки, кроме WIN32-API.

Если вы знаете, где я могу найти информацию об этом (книги, справочные материалы и т. Д.), Пожалуйста, предложите один.

Буду очень признателен за вашу помощь.

1 Ответ

10 голосов
/ 25 октября 2009

Да, вам нужно изменить идентификатор класса вашего объекта, если вы хотите, чтобы несколько версий сосуществовали. Однако вы можете поддерживать независимый от версии идентификатор программы , такой как «Word.Application» или «InternetExplorer.Application», который перенаправляет на идентификатор класса текущей версии . Обратную совместимость очень сложно поддерживать. MSXML, по-видимому, отказался от практики независимого от версии progID.

Если вы решили сохранить старые интерфейсы (рекомендуется), вам необходимо реализовать как новый, так и старый интерфейсы в новом объекте.

Возможно, вы захотите проверить реестр Microsoft Office. Он хорошо поддерживает обратную совместимость.

Предложенное имя новых интерфейсов будет следующим: имя и номер версии, например IHtmlDocument6 .

...