0

最近、DLL で COM コクラス/インターフェイスを作成および実装するプロジェクトを継承しました。この COM DLL は、GUI を COM クラスのインターフェイスに適用するアプリケーションによって利用されます。これは、COM DLL を使用する唯一のアプリケーションです。私は COM を扱うのが初めてで、適切なドキュメントを見つけるのが難しいです。

私のタスクの一部には、インターフェイスにいくつかのメソッド/プロパティを追加する (および不要になったものを削除する) ことが含まれます。これを実現するには、IDL を変更する必要があることを知りました。現在、新しいメソッドとプロパティをインターフェイスの最後に追加しただけで、うまく機能しているようです。ただし、プロパティの 1 つを削除すると (たとえば)、アプリケーションを実行するとすぐに問題が発生します。

interface IMyComInterface : IDispatch
    {
        [id(1), helpstring("method CheckMessage")] HRESULT CheckMessage([in] VARIANT vMsg);
        [id(2), helpstring("method CheckFolder")] HRESULT CheckFolder([in] VARIANT Folder, [out] VARIANT *pCount, [out, retval] VARIANT *pErrorCount);
        //[propget, id(3), helpstring("property Flags")] HRESULT Flags([out, retval] VARIANT *pVal);
        //[propput, id(3), helpstring("property Flags")] HRESULT Flags([in] VARIANT newVal);
        [propget, id(4), helpstring("property MessageStore")] HRESULT MessageStore([out, retval] VARIANT *pVal);
        [propput, id(4), helpstring("property MessageStore")] HRESULT MessageStore([in] VARIANT newVal);
        [propget, id(5), helpstring("property Directory")] HRESULT Directory([out, retval] VARIANT *pVal);
        [propput, id(5), helpstring("property Directory")] HRESULT Directory([in] VARIANT newVal);
    }

私はそれが壊れたID番号シーケンスに関係していると推測しています. その下のすべてを上に移動できれば、うまくいくと思います。しかし、これらすべてを行うための適切な方法に興味があります。

どうもありがとう。

4

2 に答える 2

2

GUI を使用IDispatch::Invokeしてメソッドを呼び出す場合、メソッド呼び出しは実行時に解決されるため (遅延バインディング)、インターフェイスの変更に対して回復力がある必要があります (ID を同じに保つ限り)。VB6 プログラムとスクリプト言語がこのように動作するのは一般的です。

ただし、GUI が直接コンパイルされる場合IMyComInterface(C++ または C# アプリである可能性が最も高い)、重要なのはインターフェイス内のメソッドの正確な順序です。メソッド呼び出しはコンパイル時に解決され (早期バインディング)、インターフェイス内のメソッドのインデックスが COM クライアントに格納されます。IDL からメソッドを削除すると、クライアントからのすべての関数呼び出しが 1 つずれます。これが、最後に新しいメソッドを追加することは機能しますが、途中でメソッドを削除することは機能しない理由です。

これらすべての問題を回避する最も簡単な方法は (COM DLL と GUI の両方を制御するため)、IDL の変更後にすべてを再コンパイルすることです。ただし、一般的なケースでは、すべてのインターフェイスを「メソッドの機能グループの不変コントラクト」 ( source ) として扱い、COM インターフェイスが世界にリリースされた後に決して変更しないでください。

于 2013-02-19T04:19:39.657 に答える
1

COM クライアントが C++ の場合、遅延バインディングの代わりに早期バインディング (インターフェイスのレイアウトが同じままであることに依存することを意味します) を使用する可能性があります。その場合、DISPID は早期バインディングではなく遅延バインディングに使用されるため、DISPID が何であるかは問題ではありません。そのため、インターフェイスからメソッド/プロパティを削除すると、クライアントを再コンパイルしない限り、クライアントが破損します。これが、COM インターフェイスを変更することをお勧めしない理由でもあります。代わりに、古いインターフェイスを継承して新しい機能を追加する新しいインターフェイスを追加することをお勧めします。

interface IMyComInterface : IDispatch
{
    // existing methods/properties
}

interface IMyComInterface2 : IMyComInterface
{
    // new methods/properties
}
于 2013-02-19T04:22:28.820 に答える