Как поздно привязать 32-битные/64-битные библиотеки во время выполнения

StackOverflow https://stackoverflow.com/questions/22322

  •  09-06-2019
  •  | 
  •  

Вопрос

У меня проблема, похожая на описанную, но немного отличающаяся от нее. здесь (Загрузка сборок и их зависимостей).

У меня есть C++ DLL для 3D-рендеринга, которую мы продаем клиентам.Для пользователей .NET у нас будет оболочка CLR.C++ DLL может быть построена как в 32-, так и в 64-битной версии, но я думаю, это означает, что нам нужно иметь две оболочки CLR, поскольку CLR привязывается к определенной DLL?

Допустим, теперь у нашего клиента есть .NET-приложение, которое может быть 32- или 64-разрядным, и что это чистое .NET-приложение, поэтому среда CLR обрабатывает его из одного набора сборок.Вопрос в том, как код приложения может динамически выбирать между нашими 32- и 64-битными комбинациями CLR/DLL во время выполнения?

Более конкретно, применим ли и здесь предлагаемый ответ на вышеупомянутый вопрос (т.е.создать обработчик ResolveEvent)?

Это было полезно?

Решение

Наконец-то у меня есть ответ на этот вопрос, который, похоже, работает.

Скомпилируйте 32- и 64-разрядные версии (управляемую и неуправляемую) в отдельные папки.Затем приложение .NET во время выполнения выбирает, из какого каталога загружать сборки.

Проблема с использованием ResolveEvent заключается в том, что он вызывается только в том случае, если сборки не найдены, поэтому очень легко случайно получить 32-битные версии.Вместо этого используйте второй объект AppDomain, где мы можем изменить свойство ApplicationBase, чтобы оно указывало на нужную папку.В итоге вы получите такой код:

static void Main(String[] argv)
  {
     // Create a new AppDomain, but with the base directory set to either the 32-bit or 64-bit
     // sub-directories.

     AppDomainSetup objADS = new AppDomainSetup();

     System.String assemblyDir = System.IO.Path.GetDirectoryName(Application.ExecutablePath);
     switch (System.IntPtr.Size)
     {
        case (4): assemblyDir += "\\win32\\";
           break;
        case (8): assemblyDir += "\\x64\\";
           break;
     }

     objADS.ApplicationBase = assemblyDir;

     // We set the PrivateBinPath to the application directory, so that we can still
     // load the platform neutral assemblies from the app directory.
     objADS.PrivateBinPath = System.IO.Path.GetDirectoryName(Application.ExecutablePath);

     AppDomain objAD = AppDomain.CreateDomain("", null, objADS);
     if (argv.Length > 0)
        objAD.ExecuteAssembly(argv[0]);
     else
        objAD.ExecuteAssembly("MyApplication.exe");

     AppDomain.Unload(objAD);

  }

В итоге у вас будет два exes — ваше обычное приложение и второе приложение-переключатель, которое выбирает, какие биты загружать.Примечание. Я не могу взять на себя ответственность за детали этого.Один из моих коллег догадался об этом, учитывая мою первоначальную подсказку.Если и когда он подпишется на StackOverflow, я передам ему ответ.

Другие советы

Мне удалось это сделать около года назад, но я уже не помню всех подробностей.По сути, вы можете использовать IntPtr.Size, чтобы определить, какую DLL загружать, а затем выполнить фактическую LoadLibrary через p/Invoke.На этом этапе у вас есть модуль в памяти, и вы должны иметь возможность просто вызывать функции p/Invoke изнутри него — одно и то же имя модуля не должно перезагружаться снова.

Однако я думаю, что в моем приложении C++ DLL зарегистрировалась как COM-сервер, а затем получила доступ к ее функциям через сгенерированную оболочку .NET, поэтому я не знаю, тестировал ли я когда-либо непосредственно p/Invoking.

Некоторое время назад я столкнулся с подобным сценарием.Набор инструментов, который я использовал, плохо себя вел в 64-битной среде, и мне не удалось найти способ динамически принудительно привязывать сборки как 32-битные.

Можно заставить ваши сборки работать в 32-битном режиме, но для этого необходимо исправить заголовок CLR (в Framework есть инструмент, который делает это), и если ваши сборки имеют строгие имена, это не сработает.

Боюсь, вам придется собрать и опубликовать два набора двоичных файлов для 32- и 64-битных платформ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top