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

Использование абсолютного пути в зондировании privatePath

В консольном приложении С# я пытаюсь использовать <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="#" onclick="location.href='http://file:///D:/Library/References/NLog.dll'; return false;"/>
    </dependentAssembly>
  </assemblyBinding>
</runtime>

но все же получил исключение System.IO.FileNotFound.

Спасибо!

4b9b3361

Ответ 1

в соответствии с MSDN:

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

Вероятно, вы пытались применить в app.config?

и

Каталоги, указанные в privatePath, должны быть подкаталогами каталог приложений.

Ответ 2

Вместо этого используйте AssemblyResolver.

Вот некоторый код, который я частично набрал из другого вопроса и изменил для нашего собственного использования. В отличие от связанного кода, он разрешает папку выполнения приложения, чего я не видел во многих других примерах. Не стесняйтесь обрезать это и придерживайтесь своего собственного абсолютного пути в случае необходимости.

Одно из преимуществ решателя сборок состоит в том, что если у вас смешанные версии ваших dll и вы хотите загрузить 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/info/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");