Как я могу отложить загрузку приватной сборки Windows? Является ли это возможным?
Мой проект представляет собой плагин (Windows DLL), который загружается исполняемым файлом узла, не находящимся под моим контролем. Моя DLL хочет загрузить несколько дополнительных библиотек. Я делаю это с частными собраниями; есть отличный ответ о том, как плагин Win32 App может загрузить свою DLL в свой собственный каталог, как это сделать. Но если я добавлю /delayload dependentlib.dll
в основной строке DLL, чтобы избежать загрузки сборки, пока она необходима (я должен сделать это по разным причинам), Windows больше не ищет мои личные сборки - похоже, она игнорирует манифест, в котором я скомпилирован. Вместо этого он ищет задержку загруженная DLL в обычном пути поиска. (Я использую sysinternals procmon, чтобы проверить это.)
Это известная ошибка или есть какой-либо другой способ отложить загрузку сборки? Я бы предпочел не идти по пути LoadLibrary + GetProcAddress, где я должен знать все символы, которые мне нужны в зависимой библиотеке.
2 ответа
Ваша проблема здесь заключается в том, что при первом вызове загруженной с задержкой функции контекст активации приложения по умолчанию является текущим контекстом.
Что вам нужно сделать, это создать контекст активации: CreateActCtx, указывающий на ваш собственный манифест (я думаю, hinstance + идентификатор ресурса возможен).
Затем оберните все или, по крайней мере, самый первый, вызов dll с ActivateActCtx (и соответствующей функцией деактивации), чтобы обеспечить поиск правильных сборок.
Теоретически вы можете просто встроить код для активации соответствующего контекста в вспомогательную функцию delayload.
Такое поведение, к сожалению, является намеренным. По сути, когда вы указываете /DELAYLOAD, вы просто указываете компоновщику вставить вызовы LoadLibrary и GetProcAddress для вас. В результате поведение при задержке загрузки DLL совпадает с динамической загрузкой этой DLL с помощью LoadLibrary.
MSDN описывает некоторые последствия. С положительной стороны, вы можете переопределить поведение по умолчанию. Я бы порекомендовал написать свою собственную вспомогательную функцию задержки загрузки.
FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd, FARPROC * ppfnIATEntry)
{
//...
}
Компоновщик вставляет вызовы этой функции всякий раз, когда ему нужно разрешить точку входа в DLL с задержкой загрузки. Ваша версия может реализовать пользовательский поиск для ваших личных сборок. Вот дополнительная информация о вспомогательной функции в MSDN.