Заставить приложение игнорировать локальные сборки и использовать 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 сценария:

  1. приложение не имеет манифеста, SxS не установлен -> приложение загружает dll локально, если не работает, иначе
  2. приложение имеет манифест, SxS не установлен -> приложение загружает dll локально, если присутствует, иначе происходит сбой
  3. приложение не имеет манифеста, SxS присутствует ->

    A. приложение загружает dll локально, если присутствует, dll затем загружает зависимость от повреждения SxS

    B. нет локальных DLL, приложение не работает

  4. приложение имеет манифест, SxS присутствует ->

    A. приложение загружает dll локально, если присутствует, dll затем загружает зависимость от повреждения SxS

    B. нет локальных DLL, приложение загружается из SxS все хорошо

Есть 2 сценария, которые мне нужны для работы:

  1. dll только в локальной папке (нет в SxS)
  2. DLL в локальной папке и SxS

Я полностью контролирую манифест приложения и dllImport, поэтому любые изменения, необходимые здесь, находятся под моим контролем. Сценарий с dll только в SxS не имеет значения.

1 ответ

Как вы устанавливаете локальные сборки? Вы пытались установить их в папку с именем сборки?

yourapp.exe
sharedSXS/ExternalDLL.dll
sharedSXS/sharedSXS.manifest
sharedSXS/OtherDLL.dll

Тогда приложения без манифеста вообще не найдут dll, а приложения с манифестом предпочтут глобальное копирование перед локальным копированием, никогда не используя оба.

Другие вопросы по тегам