他のいくつかの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
?)
このページ から(テストされていない):
プログラムの初期化のどこかで(参照されるアセンブリからクラスにアクセスする前に)これを行います:
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>
から Tomek で回答: c#のSetdllDirectoryで指定されたパスからdllをロード
var dllDirectory = @"C:/some/path";
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";" + dllDirectory)
それは私にとって完璧に機能します!
続行する別の方法があります廃止された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
を使用することができませんでした。面倒です。