在探测privatePath时使用绝对路径

时间:2012-03-02 15:51:41

标签: c#

在C#控制台应用程序中,我正在尝试使用<probing privatePath=""/>指向不在我的应用程序子目录中的dll。我正在使用:

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <probing privatePath="D:\Library\References" />
    </assemblyBinding>
</runtime>    

这不起作用,因为privatePath正在我的应用程序中查找子目录。有没有办法以这种方式使用绝对路径?如果没有,指向位于我的应用程序之外的dll的最佳方法是什么?我还尝试将<codebase>file:///路径一起使用,但仍然有System.IO.FileNotFound例外。

<runtime>
  <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
    <dependentAssembly>
      <assemblyIdentity 
        name="MyLibrary" publicKeyToken="29989D7A39ACF230" />
      <codeBase
        version="2.0.0.0"
        href="http://file:///D:/Library/References/NLog.dll"/>
    </dependentAssembly>
  </assemblyBinding>
</runtime>

但仍然有System.IO.FileNotFound例外。

谢谢!

2 个答案:

答案 0 :(得分:15)

根据MSDN

  

您只能在计算机配置或中使用该元素   发布商政策文件,它还会重定向程序集版本。   ...   如果要为不是的程序集提供代码基础提示   强名称,提示必须指向应用程序库或a   应用程序基目录的子目录。

您可能尝试申请加入app.config

  

privatePath中指定的目录必须是。的子目录   应用程序基目录。

答案 1 :(得分:0)

在这种情况下,请改用AssemblyResolver。

以下是我部分from another question编写并修改为自己使用的一些代码。与链接的代码不同,此代码可解析应用程序执行文件夹,这在许多其他示例中都没有看到。随意删除它,并在必要时坚持自己的绝对路径。

程序集解析器的一个优点是,如果您使用的是dll的混合版本,并且想要从目标文件夹而不是应用程序附带的dll中加载dll,则可以使用config file方法没有。

我遇到了这个问题,因为我们的应用程序附带了一个小的实用程序,它是应用程序的升级程序,并且它通常需要引用比原始应用程序更新的dll版本。 (升级程序会更新,然后升级程序会更新主应用程序。如果它们都使用相同的dll,则可能会发生不良情况。)

public static class AssemblyResolver
{
    internal static void Hook(params string[] folders)
    {
        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        {
            // Check if the requested assembly is part of the loaded assemblies
            var loadedAssembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == args.Name);
            if (loadedAssembly != null)
                return loadedAssembly;

            // This resolver is called when a loaded control tries to load a generated XmlSerializer - We need to discard it.
            // http://connect.microsoft.com/VisualStudio/feedback/details/88566/bindingfailure-an-assembly-failed-to-load-while-using-xmlserialization

            var n = new AssemblyName(args.Name);

            if (n.Name.EndsWith(".xmlserializers", StringComparison.OrdinalIgnoreCase))
                return null;

            // http://stackoverflow.com/questions/4368201/appdomain-currentdomain-assemblyresolve-asking-for-a-appname-resources-assembl

            if (n.Name.EndsWith(".resources", StringComparison.OrdinalIgnoreCase))
                return null;

            string assy = null;
            // Get execution folder to use as base folder
            var rootFolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)??"";

            // Find the corresponding assembly file
            foreach (var dir in folders)
            {
                assy = new[] { "*.dll", "*.exe" }.SelectMany(g => Directory.EnumerateFiles(Path.Combine(rootFolder,dir), g)).FirstOrDefault(f =>
                {
                    try
                    {
                        return n.Name.Equals(AssemblyName.GetAssemblyName(f).Name,
                            StringComparison.OrdinalIgnoreCase);
                    }
                    catch (BadImageFormatException)
                    {
                        return false; /* Bypass assembly is not a .net exe */
                    }
                    catch (Exception ex)
                    {
                        // Logging etc here
                        throw;
                    }
                });

                if (assy != null)
                    return Assembly.LoadFrom(assy);
            }

            // More logging for failure here
            return null;
        };
    }
}

在提供用于程序集解析的路径列表时尽早调用此方法

AssemblyResolver.Hook("upglib","myOtherFolder");