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的探测路径中可访问。
如何访问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;
}