Заставить приложение игнорировать локальные сборки и использовать SxS или наоборот
У меня есть приложение, которое разворачивается в 2 вариантах, с установщиком WiX лично от администратора или с установщиком с однократным нажатием пользователем без повышенных привилегий. Он зависит от набора сторонних библиотек, которые предназначены для развертывания в режиме SxS. Однако из-за необходимости установки повышенных привилегий для установки в winSxS при установке в один клик файлы должны быть установлены локально в каталог bin приложения. Это возможно и при установке WiX, и не вызывает проблем, однако есть проблема...
Другие сторонние (или четвертые) приложения, использующие тот же набор DLL, устанавливают их в winSxS, и когда наше приложение загружается, оно обращается как к локальной версии, так и к версии в winSxS. Это вызывает некоторое странное повреждение пользовательского интерфейса в отношении ресурсов, загружаемых из неуправляемых ресурсов DLL библиотеками SxS.
Для усложнения ситуации все dll в общем наборе SxS от стороннего производителя имеют встроенный манифест, который определяет зависимость от набора SxS напрямую.
Я попытался добавить в манифест приложения зависимость от набора SxS, но проблема остается, что обе версии доступны:
<dependency>
<dependentAssembly>
<assemblyIdentity name="sharedSXS" version="12.1.369.0" publicKeyToken="1255b113b2b03444" type="win32"/>
</dependentAssembly>
</dependency>
но сверху безрезультатно.
У меня вопрос такой:
Существует ли способ продолжить успешное выполнение приложения, если на компьютере не установлено никаких других приложений, а библиотеки DLL находятся в каталоге bin приложения, а также успешно запущено, если другое приложение устанавливает библиотеки DLL в winSxS. Другими словами, могу ли я заставить приложение загружаться исключительно из winSxS или локально, что когда-либо присутствует в обоих сценариях, где dll существует в winSxS или нет.
Дополнительная информация
Приложение обращается к dll, используя dllImport:
[DllImport("ExternalDll.dll", EntryPoint = "_DoStuff@12")]
[CLSCompliantAttribute(false)]
public static extern IntPtr DoStuffEx(string name, string reserved, uint uiFlags);
и DLL имеет встроенный манифест:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity name="ExternalDLL.dll" processorArchitecture="x86" type="win32" version="12.0.0.0"></assemblyIdentity>
<dependency>
<dependentAssembly>
<assemblyIdentity name="sharedSXS" version="12.1.369.0" publicKeyToken="1255b113b2b03444" type="win32"/>
</dependentAssembly>
</dependency>
</assembly>
и SxS Manifest выглядит следующим образом:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="sharedSXS" version="12.1.369.0" publicKeyToken="1255b113b2b03444"></assemblyIdentity>
<file name="ExternalDLL.dll" hashalg="SHA1" hash="cb2ecfaca2d62cd9f5c559cf21d502921881155f"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>BLyJ40vJD++ih9XTg0oOcZhISl4=</dsig:DigestValue></asmv2:hash></file>
<file name="OtherDLL.dll" hashalg="SHA1" hash="246d082823724f42d5630dba1b9dcde3e2c1b76d"><asmv2:hash xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"><dsig:Transforms><dsig:Transform Algorithm="urn:schemas-microsoft-com:HashTransforms.Identity"></dsig:Transform></dsig:Transforms><dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></dsig:DigestMethod><dsig:DigestValue>me1EL8p76nkfD1o9L058m8GUdaw=</dsig:DigestValue></asmv2:hash></file>
</assembly>
Есть 4 сценария:
- приложение не имеет манифеста, SxS не установлен -> приложение загружает dll локально, если не работает, иначе
- приложение имеет манифест, SxS не установлен -> приложение загружает dll локально, если присутствует, иначе происходит сбой
приложение не имеет манифеста, SxS присутствует ->
A. приложение загружает dll локально, если присутствует, dll затем загружает зависимость от повреждения SxS
B. нет локальных DLL, приложение не работает
приложение имеет манифест, SxS присутствует ->
A. приложение загружает dll локально, если присутствует, dll затем загружает зависимость от повреждения SxS
B. нет локальных DLL, приложение загружается из SxS все хорошо
Есть 2 сценария, которые мне нужны для работы:
- dll только в локальной папке (нет в SxS)
- DLL в локальной папке и SxS
Я полностью контролирую манифест приложения и dllImport, поэтому любые изменения, необходимые здесь, находятся под моим контролем. Сценарий с dll только в SxS не имеет значения.
1 ответ
Как вы устанавливаете локальные сборки? Вы пытались установить их в папку с именем сборки?
yourapp.exe
sharedSXS/ExternalDLL.dll
sharedSXS/sharedSXS.manifest
sharedSXS/OtherDLL.dll
Тогда приложения без манифеста вообще не найдут dll, а приложения с манифестом предпочтут глобальное копирование перед локальным копированием, никогда не используя оба.