56

我有一个 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?)

4

3 回答 3

88

从此页面(未经我测试):

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

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

编辑: 这篇文章说 AppendPrivatePath 被认为是过时的,但也提供了一种解决方法。

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

<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <probing privatePath="bin\DLLs" />
    </assemblyBinding>
  </runtime>
</configuration>
于 2009-12-12T06:04:08.757 回答
27

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

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

它非常适合我!

于 2014-03-21T12:16:04.753 回答
10

这是不使用 obsoleteAppendPrivatePath的另一种方法。它捕获一种事件“关联的 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,太费劲了。

于 2015-05-13T12:35:22.740 回答