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

时间:2009-12-12 05:55:52

标签: c# dll reference delay-load

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

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

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

如果没有,C#中首选的方法是什么来实现我所追求的目标(即LoadLibrary / Assembly.Load / Assembly.LoadFile的某些内容?可能是Assembly.LoadFrom中的某些内容,还是AppDomain?)

3 个答案:

答案 0 :(得分:75)

来自this page(未经我测试):

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

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

编辑: This article表示AppendPrivatePath被认为已过时,但也提供了解决方法。

编辑2:看起来最简单,最常用的方法是在app.config文件中(参见here):

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

答案 1 :(得分:21)

Tomek回答:Loading dlls from path specified in SetdllDirectory in c#

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

它对我来说很完美!

答案 2 :(得分:8)

这是另一种在不使用过时的AppendPrivatePath 的情况下继续的方法。它捕获了一种事件&#34; 关联的dll未找到&#34; (因此只有在默认目录中找不到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,这太费力了。