c# .net

c# - AppDomain.CurrentDomain.SetupInformation.PrivateBinPath es nulo



.net (5)

¿Cómo puedo acceder a la ruta de sondeo configurada en MyApp.exe.config?

Para seguir siendo compatible con lo que hará la fusión, puede leer el archivo de configuración vigente para obtener las rutas de sondeo actuales:

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; }

Suponiendo que la muestra del archivo de configuración en su pregunta devuelve: "Dir1; Dir2; Dir3"

Cuando inicio mi aplicación que solo tiene un dominio de aplicación, AppDomain.CurrentDomain.SetupInformation.PrivateBinPath es nulo. A pesar de que tengo rutas de sondeo establecidas en MyApp.exe.config como se muestra a continuación.

Hubiera esperado que AppDomain.CurrentDomain.SetupInformation.PrivateBinPath contenga la cadena "Dir1;Dir2;Dir3" .

¿Cómo puedo acceder a la ruta de sondeo configurada en 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>

Actualizar

Como Hans Passant señaló el comentario a continuación , SetupInformation.PrivateBinPath no está configurado para el dominio de aplicación principal. Así que lo anterior no funciona. ¿Cuál sería su sugerencia para simular la forma en que la fusión busca ensamblajes en la ruta de sondeo o al menos tener en cuenta a <probing privatePath="" /> de la configuración de la aplicación actual? Lo mejor que se me ocurre es leer <probing privatePath="" /> de App.config manualmente cuando el dominio actual es el dominio de aplicaciones primario ( AppDomain.CurrentDomain.IsDefaultAppDomain() es true ). ¿Hay alguna manera mejor?

Actualización 2

Aquí hay información adicional sobre los antecedentes para lo que se necesita: Este problema ocurrió en AppDomainAssemblyTypeScanner.GetAssemblyDirectories() del marco de Nancy .

Nancy detecta automáticamente y carga módulos de terceros y otros "complementos". De forma predeterminada, se supone que esto se debe hacer de la misma manera en que se cargarían los ensamblajes normalmente vinculados (es decir, como lo haría la fusión) observando las rutas de sondeo. Los ensamblajes se cargan utilizando Assembly.Load (a diferencia de Assembly.LoadFrom ), por lo que entiendo, todos los ensamblados dependientes de los ensamblados cargados deben ser accesibles en la ruta de sondeo de la aplicación / dominio de aplicación también.


Inspirado por la solución de , he creado una función sin necesidad de hacer referencia a 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; }


Si este es un problema de que los ensamblajes no se carguen, un método que he encontrado que funciona de manera efectiva es usar el evento AppDomain.AssemblyResolve que se activa cuando el dominio de aplicación no carga un ensamblaje ...

Trabajando con el evento AppDomain.AssemblyResolve

p.ej

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


Siempre he encontrado que lo más fácil es interceptar el evento AppDomain.AssemblyResolve . Luego, puede cargar el ensamblaje que desee desde cualquier lugar y devolverlo. Aún puede guardar su configuración en la aplicación Configuración ... Incluso podría probar la sección de ruta si desea usarla. Una cosa a tener en cuenta es que los conjuntos cargados utilizando Assembly.Load no terminan en el mismo contexto de carga que los conjuntos cargados bajo el contexto de carga predeterminado ( https://msdn.microsoft.com/en-us/library/dd153782(v=vs.110).aspx ). Esto tiene el efecto de cambiar la forma en que se produce la resolución de tipos y ensamblajes para resoluciones posteriores (después de la llamada inicial a Assembly.Load). En consecuencia, es posible que desee interceptar AppDomain.TypeResolve así como AssemblyResolve ... y querrá almacenar en caché los Ensamblados que carga desde AssemblyResolve ... de lo contrario, las resoluciones posteriores PUEDEN cargar el mismo ensamblaje nuevamente (dependiendo de cómo llame Montaje.carga


No es una respuesta, no cabe como comentario.

Como se dijo anteriormente, el dominio de aplicación predeterminado no usa AppDomainSetup para la configuración de sondeo de ruta. En lugar de esto, la ruta de prueba se lee desde el archivo .appconfig y no se expone en el código administrado.

* la aplicación auto alojada en el clr completo puede anular el comportamiento con ICustomAppDomainManager personalizado (o IHostAssemblyManager) pero eso está fuera del alcance de la pregunta.

Así que solo hay tres enfoques posibles:

  • Primero, puede llamar a Nancy.Bootstrapper.AppDomainAssemblyTypeScanner.LoadAssemblies(somedir, "*.dll") por su cuenta
  • En segundo lugar, puede envolver el host de nancy en un dominio de aplicación secundario con un conjunto de rutas de acceso privadas personalizadas.
  • Tercero: espere https://github.com/NancyFx/Nancy/pull/1846 y use IResourceAssemblyProvider personalizado.

En cualquier caso necesitará la lista de directorios de ensamblaje. Si no desea almacenar la copia como valor de <appSettings> , tendrá que analizar el archivo appconfig por usted mismo.