Есть ли LoadLibraryEx
функция использования параллельных манифестов? У меня есть bar.dll со встроенным манифестом SxS, и этот манифест описывает версию этого bar.dll, другой dll-файл foo.dll имеет манифест, который перечисляет bar.dll как зависимость с указанной версией. Но когда я пытаюсь загрузить bar.dll из foo.dll с LoadLibraryEx("bar.dll", NULL, 0)
Я вижу (с включенным sls с gflags), что он игнорирует эти манифесты и загружает первую версию bar.dll, которую видит в searchpath, если я определяю ISOLATION_AWARE_ENABLED
и использовать LoadLibrary
он находит правильную версию, но это ISOLATION_AWARE_ENABLED
не влияет на поведение LoadLibraryEx
Мне нужно загрузить правильную версию с LoadLibraryEx
так как LoadLibraryEx
используется неявно для отложенной загрузки DLL. Является LoadLibraryEx
должен работать так, или это какая-то проблема в конфигурации моего проекта?
фу длл
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="foo" version="0.1.2.3" type="win32"/>
<dependency>
<dependentAssembly>
<assemblyIdentity name="bar" version="0.1.2.3" type="win32" />
</dependentAssembly>
</dependency>
<file name="foo.dll">
</file>
</assembly>
bar.dll
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="bar" version="0.1.2.3" type="win32"/>
<file name="bar.dll">
</file>
</assembly>
LoadLibrary
использовал активный контекст активации вызывающего потока. но что это за контекст? почему это должно быть от вашего foo.dll
? почему не из xyz.dll
или из exe? действительно, наиболее активным контекстом активации времени был именно exe.
если у dll есть собственный манифест — система создает контекст активации для этой dll и сохраняет его (пока dll не будет выгружен), но не делает его активным. и это очевидно — у нас есть несколько dll в процессе, но активный контекст только один — из какой dll его выбрать? из exe. однако система активирует (делает ее активной) контекст активации dll перед вызовом точки входа. и деактивировать его после возврата к точке входа. но скажем внутри других функций dll — (кто это вызвал?) контекст уже не из вашей dll.
поэтому решение должно быть следующим:
определить 2 глобальные переменные в dll:
BOOL gActCtx;
HANDLE ghActCtx
на DLL_PROCESS_ATTACH
сохранить текущий контекст активации (это из вашего dll-манифеста)
gActCtx = GetCurrentActCtx(&ghActCtx);
освободи его на DLL_PROCESS_DETACH
if (gActCtx) ReleaseActCtx(ghActCtx);
и когда вам нужно загрузить bar.dll
делать дальше:
if (gActCtx)
{
ULONG_PTR Cookie;
if (ActivateActCtx(ghActCtx, &Cookie))
{
LoadLibraryExW(L"bar.dll", NULL, 0);
DeactivateActCtx(0, Cookie);
}
}
Других решений пока нет …