AppDomain.CurrentDomain.SetupInformation.PrivateBinPath is n

本文关键字:is PrivateBinPath SetupInformation CurrentDomain AppDomain | 更新日期: 2023-09-27 18:19:15

当我启动只有一个AppDomain的应用程序时,AppDomain.CurrentDomain.SetupInformation.PrivateBinPath为null。即使我在MyApp.exe中设置了探测路径。配置如下所示:

我希望AppDomain.CurrentDomain.SetupInformation.PrivateBinPath包含字符串"Dir1;Dir2;Dir3"

如何访问MyApp.exe.config中配置的探测路径?

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <appSettings>
    <add key="Foo" value="Bar" />
  </appSettings>
  <startup>
    <!-- supportedRuntime version="v1.1.4322" / -->
  </startup>
  <runtime>
    <gcConcurrent enabled="true" />
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <publisherPolicy apply="yes" />
      <!-- Please add your subdirectories to the probing path! -->
      <probing privatePath="Dir1;Dir2;Dir3" />
    </assemblyBinding>
  </runtime>
  <system.windows.forms jitDebugging="true" />
</configuration>

正如Hans Passant在下面的评论中指出的那样,SetupInformation.PrivateBinPath没有被设置为主应用域。所以上面的方法不起作用。您的建议是如何模拟融合在探测路径中搜索组件的方式,或者至少从当前应用程序配置中考虑<probing privatePath="" /> ?我能想到的最好的办法是,当当前域是主应用域(AppDomain.CurrentDomain.IsDefaultAppDomain()true)时,手动从App.config中读取<probing privatePath="" />。有没有更好的办法?

更新2

这个问题发生在Nancy框架的AppDomainAssemblyTypeScanner.GetAssemblyDirectories()中。

Nancy自动发现和加载第三方模块和其他"插件"。默认情况下,这应该以与通常连接的组件加载方式相同的方式完成(即,通过查看探测路径来完成融合)。程序集是使用Assembly.Load(而不是Assembly.LoadFrom)加载的,所以据我所知,加载程序集的所有依赖的程序集也必须在应用程序/appdomain的探测路径中可访问。

AppDomain.CurrentDomain.SetupInformation.PrivateBinPath is n

如何访问MyApp.exe.config中配置的探测路径

为了与fusion兼容,你可以读取配置文件来获取当前的探测路径:

private static string GetProbingPath()
{
    var configFile = XElement.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
    var probingElement = (
        from runtime 
            in configFile.Descendants("runtime")
        from assemblyBinding 
            in runtime.Elements(XName.Get("assemblyBinding", "urn:schemas-microsoft-com:asm.v1"))
        from probing 
            in assemblyBinding.Elements(XName.Get("probing", "urn:schemas-microsoft-com:asm.v1"))
        select probing)
        .FirstOrDefault();
    return probingElement?.Attribute("privatePath").Value;
}

假设你的问题中的配置文件示例返回:"Dir1; Dir2; Dir3 "

没有答案,不适合作为注释

如上所述,默认的appdomain不使用AppDomainSetup进行路径探测配置。与此相反,探测路径是从.appconfig文件中读取的,而不是暴露在托管代码中。

*在完整的clr上自托管的应用程序可以覆盖自定义ICustomAppDomainManager(或IHostAssemblyManager)的行为,但这超出了问题的范围。

所以只有三种可能的方法:

  • 首先,可以自己调用Nancy.Bootstrapper.AppDomainAssemblyTypeScanner.LoadAssemblies(somedir, "*.dll")
  • 第二,你可以包装南茜主机到辅助应用域与自定义私有bin路径设置。
  • 第三:等待https://github.com/NancyFx/Nancy/pull/1846并使用自定义IResourceAssemblyProvider

在任何情况下,你都需要程序集目录列表。如果您不想将副本存储为<appSettings>值,则必须自己解析appconfig文件。

我一直发现最简单的事情是拦截AppDomain.AssemblyResolve事件。然后,您可以从您想要的任何地方加载任何程序集并返回它。你仍然可以将你的设置存储在appConfig…如果你特别想使用它,你甚至可以探测路径部分。需要注意的一点是,使用Assembly加载的程序集。Load不会在与默认加载上下文(https://msdn.microsoft.com/en-us/library/dd153782(v=vs.110).aspx)下加载的程序集相同的加载上下文中结束。这将改变类型和程序集解析在后续解析中发生的方式(在初始调用assembly . load之后)。因此,您可能希望拦截AppDomain.TypeResolve以及AssemblyResolve…你会想要缓存从AssemblyResolve加载的程序集…否则,后续解析可能会再次加载相同的程序集(取决于您如何调用assembly . load)

如果这是程序集未加载的问题,我发现有效的一种方法是使用AppDomain。当应用域加载程序集失败时触发的AssemblyResolve事件…

使用AppDomain。AssemblyResolve事件

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(LoadManually);
private Assembly LoadManually(object sender, ResolveEventArgs args)
{
   ....
    return Assembly.LoadFrom(whereEverYouLike);
}

受g.p pickardou解决方案的启发,我创建了一个不需要引用System.Xml.Linq:

的函数。
private static string GetProbingPath()
{
    var xmlDoc = new XmlDocument();
    xmlDoc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
    var privatePathAttribute = xmlDoc.SelectSingleNode("/*[name()='configuration']/*[name()='runtime']/*[name()='assemblyBinding']/*[name()='probing']/@privatePath");
    return (privatePathAttribute as XmlAttribute)?.Value;
}