Сообщество программистов Autodesk в СНГ

ADN Club => Revit API => Тема начата: Olga от 15-03-2021, 10:47:51

Название: Путь к связанным библиотекам
Отправлено: Olga от 15-03-2021, 10:47:51
Добрый день.
У меня dll файл 1 лежит в корпоративной сети в нем есть ссылка на файл 2(методы  файла 2 используются в файле 1) который так же лежит в корпоративной сети. Так же есть файл addins который лежит  в C:\ProgramData\Autodesk\Revit\Addins\2020 и ссылается на файл 1. В основном все работает исправно, но есть пара  ПК которые при запуске надстройки не видят файл2 и выводится ошибка. Может быть кто то сталкивался с таким: в чем может быть дело?
Название: Re: Путь к связанным библиотекам
Отправлено: Александр Пекшев aka Modis от 15-03-2021, 14:51:43
Пути в корпоративной сети имеют адрес, типа
Цитировать
////copmpany@aaa.ru/folder/folder/
Такие пути не будут работать в addin файле. Чтобы использовать пути в локальной сети у пользователей добавляют виртуальный диск, который ведет к нужному пути. Получается что-то типа
Цитировать
L:/folder/folder/
И чтобы у всех нормально работало, у всех должен быть создан одинаковый виртуальный диск
Название: Re: Путь к связанным библиотекам
Отправлено: Александр Ривилис от 15-03-2021, 15:00:48
Olga,
Код - C# [Выбрать]
  1. AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
А в CurrentDomain_AssemblyResolve
Код - C# [Выбрать]
  1. System.Reflection.Assembly.LoadFile("полный путь к файл1");
  2. System.Reflection.Assembly.LoadFile("полный путь к файл2");

Название: Re: Путь к связанным библиотекам
Отправлено: Olga от 17-03-2021, 07:13:09
Это где то близко. Вставляю сюда:
Код - C# [Выбрать]
  1. public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
  2.         {  
  3.             AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
  4. //далее идет ссылка на вторую библиотеку
  5.   return Result.Succeeded;
  6.         }
  7.         public Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
  8.         {
  9.  
  10.             Assembly assembly = Assembly.LoadFile(@"Путь ко второй библиотеке ");
  11.             return assembly;
  12.         }
  13.  
Но все равно выводится ошибка. Еще странная  история у таких ПК . Если  кладешь обе  сборки  dll БЕЗ addins в папку C:\ProgramData\Autodesk\Revit\Addins\2020. надстройка загружается!!! и прорабатывает(ошибок не выдает), но видимо  все равно не все считывает т.к расчет производит не полный.
Название: Re: Путь к связанным библиотекам
Отправлено: Александр Пекшев aka Modis от 17-03-2021, 08:56:06
Попробуйте без AssemblyResolve всегда загружать библиотеки методом
Код - C# [Выбрать]
  1. System.Reflection.Assembly.LoadFrom("полный путь к файл1");
Название: Re: Путь к связанным библиотекам
Отправлено: Александр Ривилис от 17-03-2021, 10:04:54
Попробуйте без AssemblyResolve всегда загружать библиотеки методом
Код - C# [Выбрать]
  1. System.Reflection.Assembly.LoadFrom("полный путь к файл1");
К сожалению этот способ работает далеко не всегда.
Должно быть как-то так (выдернул из своего кода для AutoCAD):

Код - C# [Выбрать]
  1.     void IExtensionApplication.Initialize()
  2.     {
  3.       // Initialize your plug-in application here
  4.       try
  5.       {
  6.         AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
  7.       }
  8.       catch { };
  9.     }
  10.     private System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
  11.     {
  12.       if (args.Name.ToUpper().StartsWith("BOUNCYCASTLE.CRYPTO"))
  13.       {
  14.         return System.Reflection.Assembly.LoadFile(AssemblyDirectory() + "\\BouncyCastle.Crypto.dll");
  15.       }
  16.       else if (args.Name.ToUpper().StartsWith("IONIC.ZIP"))
  17.       {
  18.         return System.Reflection.Assembly.LoadFile(AssemblyDirectory() + "\\Ionic.Zip.dll");
  19.       }
  20.       else if (args.Name.ToUpper().StartsWith("ITEXT"))
  21.       {
  22.         return System.Reflection.Assembly.LoadFile(AssemblyDirectory() + "\\itextsharp.dll");
  23.       }
  24.       return null;
  25.     }
  26.  
  27.     public static string AssemblyDirectory()
  28.     {
  29.       string codeBase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
  30.       UriBuilder uri = new UriBuilder(codeBase);
  31.       string path = Uri.UnescapeDataString(uri.Path);
  32.       return System.IO.Path.GetDirectoryName(path);
  33.     }
  34.  
Идея должна быть понятна - грузится именно та dll - которая в этот момент требуется системе. Здесь считается, что все сборки в одном каталоге.
Название: Re: Путь к связанным библиотекам
Отправлено: Александр Ривилис от 17-03-2021, 12:17:16
Но это всё справедливо для managed сборок. Если используется native dll-файлы, то их нужно принудительно загрузить при помощи функции LoadLibrary:
Код - C# [Выбрать]
  1. [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  2. private static extern IntPtr LoadLibrary(string libpath);
Название: Re: Путь к связанным библиотекам
Отправлено: Olga от 24-03-2021, 08:27:57
System.Reflection.Assembly.LoadFrom(
Именно это решение сработало! Благодарю  всех! Просто гора с плеч)
Название: Re: Путь к связанным библиотекам
Отправлено: doctorRAZ от 02-12-2022, 12:04:01
грузится именно та dll - которая в этот момент требуется системе
хотел бы уточнить..
если разные сборки (разных разработчиков) используют этот код, не будут ли конфликтовать?
просто при отладке обратил внимание, что
CurrentDomain_AssemblyResolve
срабатывает и тогда когда "чужая" сборка ищет ресурс
--------------
upd проверил
событие срабатывает во всех сборках (которые на него подписаны) до тех пор пока не будет загружена нужная сборка или все сборки не вернут null