LoadLibrary () не может загрузить DLL с манифестом и частной сборкой - PullRequest
8 голосов
/ 25 февраля 2010

Я работаю над приложением Windows (EXE), которое использует несколько библиотек DLL. Разработка ведется в VCExpress 2005 (VC 8.0) с использованием только C.

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

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

С MSVC6 это просто: компилируйте, связывайте, распространяйте EXE и DLL.

В MSVC8 библиотека времени выполнения C (MSVCRT) больше не распространяется с ОС, поэтому нельзя полагаться на ее установку. Чтобы удовлетворить требования переносимости, мне нужно использовать частную сборку . Все EXE и DLL имеют встроенные манифесты.

Моя проблема : подключаемые библиотеки DLL, загружаемые с помощью LoadLibrary(), не находят приватную сборку, находящуюся в папке EXE, поэтому попытка загрузить их не удалась, если сборка Microsoft.VC80.CRT не установлена ​​в Winsxs.

Подвох : если манифесты удалены из DLL подключаемого модуля, все работает.

Мои вопросы :

  1. В проблемном случае Windows, похоже, не следует ни последовательности поиска Assembly , ни порядку поиска библиотеки динамических ссылок . В частности, он ищет закрытую сборку по пути, из которого была загружена DLL, а не из которого загружалось приложение (EXE).
    Я попытался проверить это, поместив сборку рядом с DLL и изменив текущий каталог (чтобы исключить связанные со случаями рабочего каталога), и получил ожидаемое поведение. Кто-нибудь еще может подтвердить, что это нормальное поведение при использовании LoadLibrary с SxS?

  2. Прав ли я, предполагая, что без манифеста DLL возвращается к порядку загрузки не-SxS, который находит msvcr80.dll (а не манифест сборки Microsoft.VC80.CRT.manifest) в папке EXE?

  3. Если я прав насчет (1) и (2), что я потеряю, просто исключив манифест из DLL? Перефразируя, почему я не должен решить мою проблему, просто исключив манифест?

Ответы [ 2 ]

10 голосов
/ 10 марта 2010

Вам необходимо понять, что такое контекст активации, чтобы понять эту проблему.

У exe, или dll, с манифестом, есть контекст активации - контекст активации - это список классов окон, зависимых сборок, dll и бесплатных ссылок на ссылки, которые были обнаружены при анализе манифеста.

Exe, или dll, без манифеста, использует контекст активации процесса по умолчанию - который обычно является контекстом активации exe, если у exe есть контекст активации.

В вашем случае, у dll есть собственный контекст активации - потому что у него есть манифест. И это всегда путь к файлу манифеста (файл / папка, содержащая), в котором выполняется поиск сборок.

Именно поэтому Windows запускается с поиска личной папки в папке dll. Затем, когда это не удается, Windows ищет стандартный путь поиска библиотеки загрузки для dll:, который начинается с корневой папки exe. Но он ищет dll's сейчас, а не сборки - поэтому папка сборки, содержащая dll, не найдена.

  1. Нет. Без манифеста dll возвращается к использованию контекста активации по умолчанию: манифеста exe. Эта статья блога объясняет это немного.

  2. Исключить манифест. Что вы теряете, так это возможность заставить dll указывать свои собственные зависимые сборки. Поэтому вам нужно добавить любые зависимые сборки, которые необходимы dll, в манифест приложения.

0 голосов
/ 25 февраля 2010

Ссылка статически с ЭЛТ. Пока вы не используете .Net в своем приложении (чистый C / C ++), возможно, существует статическая связь с CRT.

Введение .Net в моем приложении заставило меня перейти от статически связанного CRT к динамически связанному CRT. Я также пытался найти способ ссылаться на библиотеки CRT локально без необходимости их явной установки, но я не нашел его. Поэтому, если возможно, статически связывайте с ЭЛТ.

...