Загрузка нескольких копий группы DLL в одном процессе

Фон
Я поддерживаю надстройку для приложения. Я использую Visual C ++ 2003.

Плагин состоит из нескольких DLL - это основная DLL, которую приложение загружает с помощью LoadLibrary, и несколько служебных DLL, которые используются основной DLL и друг другом.
Зависимости обычно выглядят следующим образом:

  • plugin.dll -> utilA.dll, utilB.dll
  • utilA.dll -> utilB.dll
  • utilB.dll -> utilA.dll, utilC.dll

Вы уловили картину.

Некоторые зависимости между библиотеками DLL зависят от времени загрузки и времени выполнения.

Все файлы DLL хранятся в каталоге исполняемого файла (не обязательно, просто так, как это работает сейчас).

Проблема
Появилось новое требование - запуск нескольких экземпляров подключаемого модуля в приложении.
Приложение запускает каждый экземпляр подключаемого модуля в своем собственном потоке, т.е. каждый поток вызывает функции, экспортируемые plugin.dll. Однако код плагина не является потокобезопасным - много глобальных переменных и т. Д.

К сожалению, исправить все это в настоящее время невозможно, поэтому мне нужен способ загрузить несколько (не более 3) копий библиотек DLL плагина в одном процессе.

Вариант 1. Подход с разными именами
Создание трех копий каждого файла DLL, чтобы у каждого файла было собственное имя. например plugin1.dll, plugin2.dll, plugin3.dll, utilA1.dll, utilA2.dll, utilA3.dll, utilB1.dll и т. д. Приложение загрузит plugin1.dll, plugin2.dll и plugin3.dll. Файлы будут в каталоге исполняемого файла.

Чтобы каждая группа DLL знала друг друга по имени (чтобы взаимозависимости работали), имена должны быть известны во время компиляции - это означает, что библиотеки DLL нужно компилировать несколько раз, только каждый раз с разными именами выходных файлов.

Не очень сложно, но я бы не хотел иметь 3 копии файлов проекта VS и не хотел бы компилировать одни и те же файлы снова и снова.

Вариант 2. Подход с параллельными сборками
Создание 3 копий файлов DLL, каждая группа в своем собственном каталоге, и определение каждой группы как сборки путем помещения файла манифеста сборки в каталог, в котором перечислены библиотеки DLL плагина.
Каждая DLL будет иметь манифест приложения, указывающий на сборку, чтобы загрузчик находил копии служебных библиотек DLL, которые находятся в том же каталоге. Манифест должен быть встроен, чтобы его можно было найти при загрузке библиотеки DLL с помощью LoadLibrary. Для этой работы я буду использовать mt.exe из более поздней версии VS, поскольку VS2003 не имеет встроенной поддержки встраивания манифеста.

Я пробовал этот подход с частичным успехом - зависимости обнаруживаются во время загрузки библиотек DLL, но не при вызове функции DLL, загружающей другую DLL.
Это кажется ожидаемым поведением согласно эта статья - контекст активации DLL используется только во время загрузки DLL, а затем он деактивирован, и используется контекст активации процесса.

Изменить: работает с ISOLATION_AWARE_ENABLED, как и ожидалось - загрузка DLL во время выполнения использует исходный контекст активации загружаемой DLL.

Вопросы
Есть другие варианты? Подойдет любое быстрое и грязное решение. :-)

Будет ли ISOLATION_AWARE_ENABLED работать даже с VS2003? Изменить: Да.

Будем очень благодарны за комментарии.

Спасибо!


person george    schedule 01.05.2010    source источник


Ответы (1)


ISOLATION_AWARE_ENABLED реализуется заголовочными файлами Windows SDK и поэтому, вероятно, вообще не будет работать с VS2003. Однако можно загрузить последнюю версию Windows 7 SDK и использовать ее с VS2003.

Вам не нужно использовать MT для связывания в манифестах. Манифесты могут быть встроены как ресурсы в среды, которые не имеют явного знания.

Добавьте следующее в файл .rc библиотеки DLL, чтобы встроить манифест. (С достаточно свежей платформой SDK RT_MANIFEST уже должен быть определен):

#define RT_MANIFEST 24 
#define APP_MANIFEST 1
#define DLL_MANIFEST 2

DLL_MANIFEST RT_MANIFEST dllName.dll.embed.manifest
person Chris Becke    schedule 02.05.2010
comment
ISOLATION_AWARE_ENABLED действительно работает с VS2003, я полагаю, что SDK, поставляемый с ним, был достаточно свежим, чтобы включать поддержку winsxs. Мне не было известно о внедрении манифестов с использованием файла .rc - спасибо за информацию. - person george; 03.05.2010