Фон
Я поддерживаю надстройку для приложения. Я использую 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? Изменить: Да.
Будем очень благодарны за комментарии.
Спасибо!