none
DLLの参照先を指定したい RRS feed

  • 質問

  • C#でアプリケーションの開発を行っております。

    開発中のアプリケーション(VSTOアドイン,DLL,クリックワンス配置)から参照しているDLL(microsoft sharepoint.client.dll,マクロソフト製)の参照ディレクトリを指定したいと思っています。

    理由は後述のとおりですが、このようなことは可能でしょうか。
    なお、アプリケーションと同じディレクトリにあるDLLを参照したいと思っております。

    【理由】
    DLLはGACにあるものを優先して読み取る仕様になっています。一方、GACではビルド番号・リビジョン番号の違いは考慮されないようです。
    そのため、当該Dllの  異なるバージョン(15.0.4444.5555  と15.0.6666.7777 など、ビルド以降だけが違う場合)はどちらも同じパスに保存されてしまいます。
    しかし、当該DLLは、ビルド・リビジョン番号の違いが、動作の違いにも影響を与えてしまうため、こちらで指定した番号のDLLを利用したいと思っております。

    一方、GACは他社との共有領域であるため、GAC内のDLLをこちらで指定した番号にはやりづらいものがあります。
    そのため、GACにDLLがある場合も、そちらを利用せず、アプリケーションと同じディレクトリにあるDLLを参照したいです。

    よろしくご回答のほどお願いいたします。

    ----

    開発環境

        Visual Studio 2013 Premium
        Windows 7 Professional (64ビット)

    想定されるインストール環境

        Windows 8, 7 / 32ビット、64ビット。


    2015年10月1日 8:57

回答

  • >「DLLはGACにあるものを優先して読み取る仕様になっています。」

    という前提条件は、.NET自体の標準仕様であり、アプリケーション(VSTOアドインDLL)側で明示的に実装している仕様ではないですよね?

    >「GACにDLLがある場合も、そちらを利用せず、アプリケーションと同じディレクトリにあるDLLを参照したいです。」

    .NETではカレントディレクトリではなくグローバルアセンブリキャッシュを第1参照とするため、特定のプライベートアセンブリを第1参照とするにはいくつかの手順が必要となります。

    参照アセンブリのパスを明示的に指定するには、アプリケーション構成ファイル(.configファイル、アプリケーションマニフェスト)のcodeBaseタグを使ってフルパスを指定するか、AppDomain.AssemblyResolveイベントを使う方法があります。

    下記のMethod 2とMethod 3を参照してください。

    How to load an assembly at runtime that is located in a folder that is not the bin folder of the application

    ただし、今回はVSTOアドインとのことなので、EXE側(アドインのホストアプリケーションとなる実行プログラム。WordやExcelなどでしょうか?)の構成ファイルを作成して配置するのは難しいと思われます。Method 2の説明と下記ページの説明を参考にして、VSTOアドインDLLプロジェクトの.dll.manifestを修正することで対処できるかもしれません。

    Visual Studio 2010 : VSTO の配置の進化 (CTP 版) (2)

    あるいはMethod 3の説明を参考にして、VSTOアドインDLLプロジェクトの中で、「Microsoft.SharePoint.Client.dll」が読み込まれる前にAssemblyResolveイベントにカスタムハンドラーを追加するように実装すれば対処できるかもしれません。

    とはいえ、署名のない野良アセンブリによるセキュリティ侵害を防ぐために、できれば標準仕様のようにGACを優先するようにしたほうがよいとは思います。

    • 回答としてマーク Harinezumi 2015年10月9日 6:12
    2015年10月4日 9:33
  • 一応、通常の exe であればこういう仕組みはある のですが、アセンブリのバージョン(ファイルバージョンではありません)が同じだとするとリダイレクトはできないかもしれませんね。(もっとも、すでに指摘のあるとおり、自前 exe でない時点で無理がありますが)
    理由としては検索シーケンスとして必ずグローバルアセンブリキャッシュが優先して入ってくる(参考)ので、アセンブリのバージョンが同じである限り、逃れられないと考えられます。

    英語圏で似たような質問でも .NET app will always look for the assembly in the GAC と述べられていますね。

    // 通常の exe でも難しい上、Office のプロセス上で動くとなると、「無理ではないですか?」が私の意見となります。
    // どちらかというと、バージョンによって不都合が起きる方についてサポートに回避策を問い合わせる方が良い気がします。

    2015年10月5日 13:41
    モデレータ

すべての返信

  • >「DLLはGACにあるものを優先して読み取る仕様になっています。」

    という前提条件は、.NET自体の標準仕様であり、アプリケーション(VSTOアドインDLL)側で明示的に実装している仕様ではないですよね?

    >「GACにDLLがある場合も、そちらを利用せず、アプリケーションと同じディレクトリにあるDLLを参照したいです。」

    .NETではカレントディレクトリではなくグローバルアセンブリキャッシュを第1参照とするため、特定のプライベートアセンブリを第1参照とするにはいくつかの手順が必要となります。

    参照アセンブリのパスを明示的に指定するには、アプリケーション構成ファイル(.configファイル、アプリケーションマニフェスト)のcodeBaseタグを使ってフルパスを指定するか、AppDomain.AssemblyResolveイベントを使う方法があります。

    下記のMethod 2とMethod 3を参照してください。

    How to load an assembly at runtime that is located in a folder that is not the bin folder of the application

    ただし、今回はVSTOアドインとのことなので、EXE側(アドインのホストアプリケーションとなる実行プログラム。WordやExcelなどでしょうか?)の構成ファイルを作成して配置するのは難しいと思われます。Method 2の説明と下記ページの説明を参考にして、VSTOアドインDLLプロジェクトの.dll.manifestを修正することで対処できるかもしれません。

    Visual Studio 2010 : VSTO の配置の進化 (CTP 版) (2)

    あるいはMethod 3の説明を参考にして、VSTOアドインDLLプロジェクトの中で、「Microsoft.SharePoint.Client.dll」が読み込まれる前にAssemblyResolveイベントにカスタムハンドラーを追加するように実装すれば対処できるかもしれません。

    とはいえ、署名のない野良アセンブリによるセキュリティ侵害を防ぐために、できれば標準仕様のようにGACを優先するようにしたほうがよいとは思います。

    • 回答としてマーク Harinezumi 2015年10月9日 6:12
    2015年10月4日 9:33
  • 回答ありがとうございます。
    ご教示いただいたホームページ
    https://support.microsoft.com/ja-jp/kb/837908
    の方法2、3を参照したのですが、どちらも失敗してしまいました。


    -方法2-
    エラーメッセージは表示されずに失敗しました。(GACのDLLが読み込まれました。)
    href属性には当該ホームページに示されているとおりのフルパスと、VSTOアプリからの相対パスの2通りを試しました。


    -方法3-
    こちらもエラーメッセージ無しで失敗しました。
    AssemblyResolve イベント自体が発火しませんでした。

    2015年10月5日 3:54
  • 一応、通常の exe であればこういう仕組みはある のですが、アセンブリのバージョン(ファイルバージョンではありません)が同じだとするとリダイレクトはできないかもしれませんね。(もっとも、すでに指摘のあるとおり、自前 exe でない時点で無理がありますが)
    理由としては検索シーケンスとして必ずグローバルアセンブリキャッシュが優先して入ってくる(参考)ので、アセンブリのバージョンが同じである限り、逃れられないと考えられます。

    英語圏で似たような質問でも .NET app will always look for the assembly in the GAC と述べられていますね。

    // 通常の exe でも難しい上、Office のプロセス上で動くとなると、「無理ではないですか?」が私の意見となります。
    // どちらかというと、バージョンによって不都合が起きる方についてサポートに回避策を問い合わせる方が良い気がします。

    2015年10月5日 13:41
    モデレータ
  • お二人とも、ご回答ありがとうございます。

    弊社アプリケーション側では、可能な限りDLLの新しいバージョンを利用し、
    エンドユーザーにはそのバージョン以降を動作環境としていただくことにして解決したいと思います。

    DLLの参照先を指定するのは、Azulean様の「無理ではないですか?」という意見により目が覚めました。
    おっしゃるとおりだと思います。

    重ねて、ありがとうございました。

    2015年10月9日 6:12
  • Azuleanさんの挙げられたURLのアセンブリバージョンのリダイレクトですが、Microsoftの場合、互換性を維持していることでしょうから、発行者ポリシーにて新バージョンに対してリダイレクトする設定もされていることでしょう。

    ただし同ページには「発行者ポリシーの省略」機能も紹介されており、発行者から提供されるバージョンリダイレクトを無視することもできるようです。その場合、コンパイル時に指定されたバージョンを読み込むことになるのかなと予想しています。(また一致するバージョンがなければエラーになるかと。)

    …これら機能としてはありますが、私自身は試したことがありません。

    2015年10月9日 6:41