Зареждане на множество копия на група от 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: Подходът с различни имена
Създаване на 3 копия на всеки 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