Подтвердить что ты не робот

AppDomain.CurrentDomain.SetupInformation.PrivateBinPath имеет значение null

Когда я запускаю приложение, у которого есть только один AppDomain, AppDomain.CurrentDomain.SetupInformation.PrivateBinPath имеет значение null. Несмотря на то, что у меня есть пути проверки, установленные в MyApp.exe.config, как показано ниже.

Я бы испробовал, что 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>

Обновление

Поскольку Ханс Пассант указал комментарий ниже, SetupInformation.PrivateBinPath не установлен для основного приложения. Таким образом, вышесказанное не работает. Каково было бы ваше предложение моделировать способ поиска fusion для сборок на пути зондирования или, по крайней мере, принять во внимание <probing privatePath="" /> из текущей конфигурации приложения? Самое лучшее, что я могу придумать, - это прочитать <probing privatePath="" /> из App.config вручную, когда текущий домен является основным доменом (AppDomain.CurrentDomain.IsDefaultAppDomain() is true). Есть ли лучший способ?

Обновление 2

Вот дополнительная информация о том, что это необходимо для: Эта проблема возникла в AppDomainAssemblyTypeScanner.GetAssemblyDirectories() Рамка Нэнси.

Нэнси автоматически обнаруживает и загружает сторонние модули и другие "плагины". По умолчанию предполагается, что это делается так же, как если бы загружались нормально связанные сборки (то есть, как это сделал fusion), просматривая траектории зондирования. Ассембли загружаются с помощью Assembly.Load (в отличие от Assembly.LoadFrom), так как я понимаю, все зависимые сборки загруженных сборок также должны быть доступны на пути исследования приложения/приложения.

4b9b3361

Ответ 1

Как я могу получить доступ к пути исследования, как это описано в файле 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"

Ответ 2

Не ответ, не подходит как комментарий

Как указано выше, приложение appdomain по умолчанию не использует AppDomainSetup для конфигурации проверки пути. Вместо этого путь обнаружения считывается из файла .appconfig и не отображается в управляемом коде.

* самообслуживаемое приложение на полном clr может переопределить поведение с пользовательским ICustomAppDomainManager (или IHostAssemblyManager), но это выходит за рамки вопроса.

Таким образом, возможны только три подхода:

  • Сначала вы можете позвонить Nancy.Bootstrapper.AppDomainAssemblyTypeScanner.LoadAssemblies(somedir, "*.dll") самостоятельно
  • Во-вторых, вы можете перенести узел nancy во вторичный appdomain с настраиваемым набором путей к отдельному ящику.
  • В-третьих: подождите https://github.com/NancyFx/Nancy/pull/1846 и используйте пользовательские IResourceAssemblyProvider.

В любом случае вам понадобится список каталогов сборки. Если вы не хотите хранить копию в качестве значения <appSettings>, вам придется самостоятельно проанализировать файл appconfig.

Ответ 3

Я всегда обнаружил, что проще всего перехватить событие 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)

Ответ 4

Если это проблема сборок, которые не загружаются, один из методов, который я нашел эффективным, - это использовать событие AppDomain.AssemblyResolve, которое запускается всякий раз, когда appdomain не может загрузить сборку...

Работа с событием AppDomain.AssemblyResolve

например.

AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(LoadManually);

private Assembly LoadManually(object sender, ResolveEventArgs args)
{
   ....
    return Assembly.LoadFrom(whereEverYouLike);
}