none
複数のプロジェクトでCOMを参照すると、Interop.***.dllが上書きされてしまう。 RRS feed

  • 質問

  • 質問させて頂きます。

    Windowsアプリケーション(aaa.exe)とクラスライブラリ(bbb.dll)のプロジェクトを1つずつ作成します。
    aaa.exeからbbb.dllを参照設定します。
    各プロジェクトは同一のキーファイルでアセンブリ署名しています。

    また、それぞれのプロジェクトでは「Microsoft Scripting Runtime」を参照設定します。
    すると、ビルド時にそれぞれ「Interop.Scripting.dll」というファイルが生成されます。

    これら2つのプロジェクトを同一のフォルダにビルドするようにすると、ビルドは正常に終了するのですが、
    実行時、以下のようなエラーメッセージが表示されます。

    「ファイルまたはアセンブリ 'Interop.Scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=****************'、またはその依存関係の 1 つが読み込めませんでした。見つかったアセンブリのマニフェスト定義はアセンブリ参照に一致しません。 (HRESULT からの例外: 0x80131040)」

    これは、aaa.exeのビルド時に、bbb.dllが作成したInterop.Scripting.dllを上書きしてしまい、
    実行時にaaa.exeから呼び出したbbb.dllが参照するInterop.Scripting.dllが見つからないのが原因なのではないかと思っています。

    解決方法を探したのですが、いい方法が見つかりませんでした。
    ご存知の方がいれば助けて頂けないでしょうか。
    よろしくおねがいします。

    【環境】
    WinXP SP3
    VS 2005 SP1

    2009年10月28日 10:17

回答

  • アセンブリに署名されている場合、そのアセンブリが参照するアセンブリも厳密な名前で参照します。
    Visual Studio から COM を参照した場合に自動で生成される代替相互運用アセンブリは、それぞれのプロジェクトで個別に生成されるため互換性がありません。
    tlbimp.exe を用いて手動で相互運用アセンブリを生成し、各プロジェクトで同じアセンブリを参照するようにしてはいかがでしょうか。

    # 理想は、(今回の場合に限らず)そのコンポーネントのメーカーにプライマリ相互運用アセンブリを提供してもらい、それを利用することです。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク HappyHill415 2009年10月29日 9:57
    2009年10月28日 15:20
    モデレータ

すべての返信

  • XP SP3・VS 2008 SP1 で試してみました。

    1ソリューションにアプリケーションとクラスライブラリとの二つのプロジェクトを作り、
    各プロジェクトで Microsoft Scripting Runtime を参照。
    各プロジェクト内で Microsoft Scripting Runtime のオブジェクトを生成し
    メソッドを実行するよう実装した上で、どちらも同一フォルダにビルドするようにしました。

    結果:何の問題もなく実行できました。(^ω^;


    VS 2005 SP1 が問題なのかはわかりませんが、手っ取り早い回避策としては
    Scripting のオブジェクトを使う処理を、リファクタリングしてクラスライブリに纏めてしまい
    アプリケーションからはクラスライブラリのクラスを呼び出すだけにするといいかと思います。

    #プロジェクトごとに作業者やチームが違えば難しいかも知れませんが・・・

    2009年10月28日 10:58
    モデレータ
  • 各プロジェクトは同一のキーファイルでアセンブリ署名しています。

    すみません、この一行を見落としてました(汗

    先のレスとは別環境 (XP SP3・VB 2005 SP1) で、上と同様の手順でプロジェクトを組み、同一のキーファイルでアセンブリ署名したら、確かに以下の例外が発生しました。

    {"ファイルまたはアセンブリ 'Interop.Scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=908f92b044047487'、
    またはその依存関係の 1 つが読み込めませんでした。見つかったアセンブリのマニフェスト定義はアセンブリ参照に一致しません。
    (HRESULT からの例外: 0x80131040)":"Interop.Scripting, Version=1.0.0.0, Culture=neutral, PublicKeyToken=908f92b044047487"}

    さらに最初の環境 XP SP3・VS 2008 SP1  でも、署名を設定したら同一の現象が確認できました。

    どちらも、以下のいずれかの方法で例外を回避することができました。

    1. アセンブリ署名を外す。

    2. もしくは署名を外さず Microsoft Scripting Runtime の参照をクラスライブラリのみにし、EXEファイルからはクラスライブラリの機能を呼び出すようにする。






    2009年10月28日 14:58
    モデレータ
  • アセンブリに署名されている場合、そのアセンブリが参照するアセンブリも厳密な名前で参照します。
    Visual Studio から COM を参照した場合に自動で生成される代替相互運用アセンブリは、それぞれのプロジェクトで個別に生成されるため互換性がありません。
    tlbimp.exe を用いて手動で相互運用アセンブリを生成し、各プロジェクトで同じアセンブリを参照するようにしてはいかがでしょうか。

    # 理想は、(今回の場合に限らず)そのコンポーネントのメーカーにプライマリ相互運用アセンブリを提供してもらい、それを利用することです。
    解決した場合は、参考になった返信に「回答としてマーク」のボタンを利用して、回答に設定しましょう(複数に設定できます)。
    • 回答としてマーク HappyHill415 2009年10月29日 9:57
    2009年10月28日 15:20
    モデレータ
  • まさにこの方法で解決できました!
    ありがとうございます。

    ファイル構成を既存のままにしたかったので、生成されるアセンブリ名を「Interop.Scripting.dll」としたところ、
    名前空間が「Scripting」ではなくて、「Interop.Scripting」になってしまいました。

    そこで、名前空間を「Scripting」と指定することで、コードも修正せずに行けました。

    ちなみにコマンドラインはこの通りです。
    tlbimp.exe c:\windows\system32\scrrun.dll /keyfile:(キーファイルパス) /out:Interop.Scripting.dll /namespace:Scripting

    2009年10月29日 10:07