web-dev-qa-db-ja.com

カスタムパスを参照DLLに設定しますか?

他のいくつかのDLLプロジェクトを参照するC#プロジェクト(MainProjと呼ぶ)があります。これらのプロジェクトをMainProjの参照に追加することにより、ビルドしてコピーします結果のDLLをMainProjの作業ディレクトリに保存します。

私がやりたいのは、これらの参照されたDLLを、作業ディレクトリ自体ではなく、MainProjの作業ディレクトリ、つまりMainProj/bin/DLLsのサブディレクトリに配置することです。

私はあまり経験のあるC#プログラマーではありませんが、C++の世界から来た場合、プロジェクト参照を削除し、パスとファイル名(つまり、C++、LoadLibrary)で必要なDLLを明示的に読み込むことを想定しています)。ただし、方法がある場合は、何らかの「参照バイナリパス」を設定するのが望ましいので、ビルド時にすべてこのサブディレクトリに自動的にコピーされます(そしてそこから参照されることなくそれぞれを明示的にロードする必要があります)。そのようなことは可能ですか?

そうでない場合、私が望んでいることを達成するためのC#の推奨方法は何ですか(つまり、Assembly.Load/Assembly.LoadFile/Assembly.LoadFrom?おそらくAppDomainの何か、またはSystem.Environment?)

49
Metal450

このページ から(テストされていない):

プログラムの初期化のどこかで(参照されるアセンブリからクラスにアクセスする前に)これを行います:

AppDomain.CurrentDomain.AppendPrivatePath(@"bin\DLLs");

編集: この記事 AppendPrivatePathは廃止されたと見なされますが、回避策も提供します。

編集2: これを行う最も簡単で最もコーシャー的な方法は、app.configファイルにあるようです( here を参照):

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-Microsoft-com:asm.v1">
      <probing privatePath="bin\DLLs" />
    </assemblyBinding>
  </runtime>
</configuration>
78
Aaron

から Tomek で回答: c#のSetdllDirectoryで指定されたパスからdllをロード

var dllDirectory = @"C:/some/path";
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";" + dllDirectory)

それは私にとって完璧に機能します!

22
Pedro77

続行する別の方法があります廃止されたAppendPrivatePathを使用せずに。 「関連付けられていないdllが見つかりません」というイベントをキャッチします(したがって、デフォルトのディレクトリでdllが見つからない場合にのみ呼び出されます)。

私のために動作します(.NET 3.5、他のバージョンはテストされていません)

/// <summary>
/// Here is the list of authorized assemblies (DLL files)
/// You HAVE TO specify each of them and call InitializeAssembly()
/// </summary>
private static string[] LOAD_ASSEMBLIES = { "FooBar.dll", "BarFooFoz.dll" };

/// <summary>
/// Call this method at the beginning of the program
/// </summary>
public static void initializeAssembly()
{
    AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs args)
    {
        string assemblyFile = (args.Name.Contains(','))
            ? args.Name.Substring(0, args.Name.IndexOf(','))
            : args.Name;

        assemblyFile += ".dll";

        // Forbid non handled dll's
        if (!LOAD_ASSEMBLIES.Contains(assemblyFile))
        {
            return null;
        }

        string absoluteFolder = new FileInfo((new System.Uri(Assembly.GetExecutingAssembly().CodeBase)).LocalPath).Directory.FullName;
        string targetPath = Path.Combine(absoluteFolder, assemblyFile);

        try
        {
            return Assembly.LoadFile(targetPath);
        }
        catch (Exception)
        {
            return null;
        }
    };
}

PS:AppDomainSetup.PrivateBinPathを使用することができませんでした。面倒です。

8
56ka