将自定义路径设置为引用的DLL?

Met*_*450 49 c# dll reference delay-load

我有一个C#项目(调用它MainProj)引用了其他几个DLL项目.通过将这些项目添加到MainProj引用中,它将构建它们并将其生成的DLL复制到MainProj的工作目录中.

我想做的是将这些引用的DLL放在MainProj工作目录的子目录中,即MainProj/bin/DLLs,而不是工作目录本身.

我不是一个非常有经验的C#程序员,但是来自C++世界,我假设一种方法是删除项目引用并通过路径和文件名显式加载所需的DLL(即在C++中LoadLibrary).然而,我更喜欢做的,如果有办法的话,就是设置某种"引用二进制路径",所以当我构建时它们都被自动复制到这个子目录中(然后从那里引用它们)我需要明确加载每个).这样的事情可能吗?

如果不是,那么C#中首选的方法是什么来实现我所追求的目标(即Assembly.Load/ Assembly.LoadFile/ Assembly.LoadFrom?某些东西AppDomain,或者System.Environment?)

Aar*_*ron 78

这个页面(我未经测试):

在程序初始化的某个地方(在从引用的程序集访问任何类之前)执行以下操作:

AppDomain.CurrentDomain.AppendPrivatePath(@"bin\DLLs");
Run Code Online (Sandbox Code Playgroud)

编辑: 本文称AppendPrivatePath被认为已过时,但也提供了一种解决方法.

编辑2:看起来最简单,最犹豫的方法是在app.config文件中(见这里):

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="bin\DLLs" />
    </assemblyBinding>
  </runtime>
</configuration>
Run Code Online (Sandbox Code Playgroud)

  • 此方法的一个限制是privatePath中指定的文件夹必须是应用程序的基本文件夹(exe所在的位置)的子文件夹.请参阅http://stackoverflow.com/questions/9536256/using-an-absolute-path-in-probing-privatepath.尝试在该父级之外指定文件夹将失败. (5认同)
  • 不,它们都不起作用,但是这篇文章:http://stackoverflow.com/questions/11410940/loading-dlls-from-path-specified-in-setdlldirectory-in-c-sharp,有效。 (3认同)

Ped*_*o77 22

来自Tomek回答:从c#中SetdllDirectory中指定的路径加载dll

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

它对我来说很完美!


56k*_*6ka 8

这是另一种不使用过时的方法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;
        }
    };
}
Run Code Online (Sandbox Code Playgroud)

PS:我没有设法使用AppDomainSetup.PrivateBinPath,这太费力了.