8

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 やその他のライブラリは使用していないことに注意してください。

これに関する情報 (書籍、参考文献など) をどこで見つけることができるか知っている場合は、1 つ提案してください。

よろしくお願いします。

4

1 に答える 1

10

はい、複数のバージョンを共存させたい場合は、オブジェクトのクラス IDを変更する必要があります。ただし、現在のバージョンのクラス ID にリダイレクトする"Word.Application" や "InternetExplorer.Application" など、バージョンに依存しないプログラム IDを維持できます。下位互換性を維持するのは非常に困難です。MSXML は、バージョンに依存しない progID の実践を放棄したようです。

古いインターフェイスを保持する場合 (推奨)、新しいオブジェクトに新しいインターフェイスと古いインターフェイスの両方を実装する必要があります。

Microsoft Office のレジストリ全体を確認することをお勧めします。下位互換性を非常によく維持します。

新しいインターフェイスの推奨される名前は、 IHtmlDocument6など、インターフェイス名とバージョン番号です。

于 2009-10-25T13:47:35.883 に答える