1

簡単に:

.NET プロジェクトで、CLSID 以外は同一の 2 つの ummanaged COM コンポーネントへの 2 つの参照を作成するにはどうすればよいですか? それらは同じ ProgID と同じ Type Lib を持っています。

Type Lib は、2 番目の参照を作成しようとしたときに、Visual Studio が不平を言うものです。

「XXX タイプ ライブラリ」への参照を追加できませんでした。このタイプ ライブラリへの参照は既に存在します。これを追加する前に、参照「XXX」を削除する必要があります。

前もって感謝します。


詳細:

別のアプリケーションとの統合を提供する WPF アプリケーションを作成しています。もう 1 つのアプリケーションは、そのバージョンが個別のアプリケーションとしてインストールされるという点で少し変わっています。ユーザーは、複数のバージョンのアプリケーションをコンピューター上で並行して実行できます。

私の単一の WPF アプリケーションでは、ユーザーがこの別のアプリケーションのバージョンを選択できるようになっています。他のアプリケーションには、インストールされている各バージョンのアンマネージ COM DLL があり、これを使用して、自分の WPF アプリとこの他のアプリケーションとの統合を作成しています。

私の WPF アプリケーションは、バージョン 1 のアンマネージ COM コンポーネントへの参照を使用して、他のアプリケーションの最初のバージョンで正常に動作しています。2 番目のバージョンの COM コンポーネントを参照しようとすると、問題が発生します。

WPF プロジェクトで [参照の追加] を使用すると、次のエラーが表示 されます。「XXX タイプ ライブラリ」への参照を追加できませんでした。このタイプ ライブラリへの参照は既に存在します。これを追加する前に、参照「XXX」を削除する必要があります。

レジストリを調べると、COM コンポーネントの 2 つのバージョンのレジストリ情報の違いは、CLSD と実際の DLL へのパスだけであることがわかります。ProgID と TypeLib の値は、両方のコンポーネントで同じです。

他のアプリケーションのバージョンは実際には別個のアプリケーションとして扱われるため、COM コンポーネントを別のアプリケーションとしてインストールすることを希望し、次のリリースで会社と協力しています。

今のところ、バージョン 2 を自分の WPF アプリケーションに統合しようとしています。extern エイリアスとプロジェクト ファイルを手動で編集してエイリアスを導入する方法に関する多くの投稿を見てきまし たが、それらはすべてアンマネージド COM コンポーネントではなくマネージド アセンブリから始まるようです。プロジェクト ファイルの内容は、参照されるアンマネージ COM コンポーネントによって異なります。また、2 番目の参照を作成できないため、プロジェクト ファイル内の参照にエイリアスタグを追加しても役に立ちません。

System.Addin とリフレクションの使用について話している人を見てきましたが、より複雑なアプローチを調査する前に、より簡単なアプローチがないことを確認したかったのです。

ここまで読んでくれてありがとう!


CasperOneのアドバイスに従って、次のことを行いました。

  1. Visual Studio コマンド プロンプトを使用して次を実行しました: tlbimp "c:\xxx1.dll" /out:"c:\NETxxx1.dll"
  2. Visual Studio コマンド プロンプトを使用して次のコマンドを実行しました: tlbimp "c:\xxx2.dll" /out:"c:\NETxxx2.dll"
  3. テスト プロジェクトへの参照として、新しく作成された両方の DLL (Interop だと思います) を追加しました。「参照」タブを使用してそれらを見つけました。
  4. casperOne のコード サンプルにほぼ従うコードを追加しました。

COM インターフェイスに使用する名前について、少しパニックになりました。私が使用している COM オブジェクトの場合、1 つのメイン インターフェイス オブジェクトがあり、その COM オブジェクトから使用する他のすべてのオブジェクトは、そのメイン インターフェイス オブジェクト内からインスタンス化されます (つまり、Foo x = y. GetNewFoo();)。

using X1 = NETXXX1; using X2 = NETXXX2; Guid clsid1 = new Guid("xxx..."); Type type1 = Type.GetTypeFromCLSID(clsid1); X1.IApplication a1 = (X1.IApplication)Activator.CreateInstance(type1); X1.FooList f1 =a1.GetFooList(); Guid clsid2 = new Guid("yyy..."); Type type2 = Type.GetTypeFromCLSID(clsid2); X2.IApplication a2 = (X2.IApplication)Activator.CreateInstance(type2); X2.FooList f2 = a2.GetFooList(); foreach(X1.Foo f in f1) Console.WriteLine(f.Name); Console.WriteLine("*****"); foreach(X2.Foo f in f2) Console.WriteLine(f.Name);

4

1 に答える 1

1

このシナリオでは、Visual Studio の [参照の追加] ダイアログから参照を追加しないことをお勧めします。

代わりに、タイプ ライブラリ インポーターを使用してコマンド ラインから参照を生成し、それへの参照を通常どおりプロジェクトに設定します (.NET アセンブリになります)。

これが完了すると、2 つの型のセット、2 つのクラスが実装するインターフェイスのセット、およびそれらのインターフェイスの実装のクラス定義の 1 つが得られます。

コンストラクターを使用してこのクラスを作成する代わりに、クラスのGetTypeFromCLSIDメソッドを使用して、COM オブジェクトの .NET を取得します。TypeType

次に、Type呼び出しでそれを使用しActivator.CreateInstance(すべての COM オブジェクトには既定のコンストラクターがあるため、これは機能します)、次のように結果をインターフェイス定義にキャストします。

// The CLSID of the implementation you want to use.
Guid clsid = ...;

// Get the type.
Type type = Type.GetTypeFromCLSID(clsid);

// Create and cast to your interface.
var i = (IMyComInterface) Activator.CreateInstance(type);

COM オブジェクトである型にActivator.CreateInstance遭遇するSystem.__ComObjectと、CLR がサポートする (すべての COM 相互運用インスタンスのルート) を作成します (IUnkown::QueryInterface上記のコードのように、キャスト時に呼び出すなど)。

また、必要に応じて、コードでインターフェイスを定義し、それらにキャストすることもできます。それらを生成するためにタイプ ライブラリ インポーターは必ずしも必要ではありません。

于 2012-11-06T18:35:24.313 に答える