Я работаю над Приложением Windows (EXE), который использует несколько DLLs. Разработка находится в 2005 VCExpress (VC 8.0), с помощью C только.
Некоторые из этих DLLs являются plug-ins/add-ons/extensions, которые динамично загружаются с помощью LoadLibrary
согласно конфигурационному файлу, считанному EXE.
Значительно: приложение должно быть портативным (в смысле способного для выполнения от карты флэш-памяти с интерфейсом USB или подобный без установки), и сменный DLLs не может быть в той же папке как приложение EXE (причины прежней версии).
С MSVC6 это просто: скомпилируйте, свяжите, распределите EXE и DLLs.
С MSVC8 Библиотека времени выполнения C (MSVCRT) больше не распределяется с ОС, таким образом, нельзя полагаться на то, чтобы он был установленным. Для удовлетворения требования мобильности, я должен использовать приватную сборку. Всему EXEs и DLLs встроили их декларации.
Моя проблема: сменный DLLs, загруженный через LoadLibrary()
не находите приватную сборку, которая находится в папке EXE, таким образом пытаясь загрузить их сбои если Microsoft.VC80.CRT
блок установлен в winSxS.
Выгода: если декларации удалены из сменного DLLs, все работает.
Мои вопросы:
В проблемном случае Windows, кажется, не следует или за последовательностью поиска блока или за порядком поиска Динамически подключаемой библиотеки. Конкретно это ищет приватную сборку в пути, из которого DLL был загружен, не, из которого было загружено приложение (EXE).
Я попытался проверить это путем помещения блока, смежного с DLL и изменения текущего каталога (для исключения связанный с рабочими случаями каталога), и получаю ожидаемое поведение. Может кто-либо еще подтверждать, что это - нормальное поведение при использовании LoadLibrary
с SxS?
Действительно ли я прав в предположении, что без декларации, DLL отступает к порядку загрузки non-SxS, который находит msvcr80.dll
(а не манифест сборки Microsoft.VC80.CRT.manifest
) в папке EXE?
Если я прав приблизительно (1) и (2), чем я проигрываю только, исключая декларацию от DLL? Перефразированный, почему я не должен решать свою проблему только, исключая декларацию?
Статическое связывание с CRT. Пока вы не используете .Net в своем приложении (чистый C/C++), можно статически связываться с CRT.
Внедрение .Net в мое приложение заставило меня перейти от статически связанной CRT к динамически связанной CRT. Я также пытался найти способ локального обращения к DLL CRT без необходимости их явной установки, но не нашел его. Поэтому, если возможно, статически связывайте с CRT.
Вам необходимо понять, что такое контекст активации, чтобы понять эту проблему.
EXE или dll с манифестом имеет контекст активации - контекст активации - это список классов окон, зависимых сборок, dll и бесплатных ссылок com, которые были обнаружены при анализе манифеста.
EXE или dll без манифеста использует контекст активации процесса по умолчанию, который обычно является контекстом активации exe, если у exe есть контекст активации.
В вашем случае у dll есть собственный контекст активации - потому что у нее есть манифест. И это всегда путь к (файлу / папке, содержащей) файл манифеста, в котором выполняется поиск сборок.
Вот почему Windows начинает с поиска частной сборки в папке dll. Затем, если это не удается, Windows выполняет поиск dll по стандартному пути поиска библиотеки загрузки: она начинается с корневой папки exe. Но теперь он ищет dll, а НЕ сборки, поэтому папка сборки, содержащая dll, не найдена.
Нет. Без манифеста dll возвращается к использованию контекста активации по умолчанию: манифеста exe. Эта статья блога немного объясняет это.
Исключить манифест. Что вы теряете, так это возможность заставить dll указывать свои собственные зависимые сборки. Поэтому вам нужно добавить в манифест приложения любые зависимые сборки, которые необходимы dll.