Перенаправление библиотеки динамической компоновки

Загрузчик DLL является частью операционной системы (ОС), которая разрешает ссылки на библиотеки DLL, загружает их и связывает их. Перенаправление библиотеки динамических ссылок (DLL) — это один из методов, с помощью которых можно повлиять на поведение загрузчика DLL и управлять тем, какой из нескольких кандидатов БИБЛИОТЕК DLL он фактически загружает.

Другие имена этой функции включают .local, Dot Local, DotLocal и Dot Local Debugging.

Проблемы с управление версиями DLL

Если приложение зависит от определенной версии общей библиотеки DLL, а другое приложение устанавливается с более новой или старой версией этой библиотеки DLL, что может привести к проблемам совместимости и нестабильности; это может привести к сбою приложения.

Загрузчик DLL выглядит в папке, из которую был загружен вызывающий процесс (папка исполняемого файла), прежде чем он будет выглядеть в других расположениях файловой системы. Поэтому одно из обходных решений — установить библиотеку DLL, необходимую приложению в папке исполняемого файла. Это эффективно делает библиотеку DLL частной.

Но это не решает проблему для COM. Две несовместимые версии COM-сервера могут быть установлены и зарегистрированы (даже в разных расположениях файловой системы), но есть только одно место для регистрации COM-сервера. Таким образом, активируется только последний зарегистрированный COM-сервер.

Вы можете использовать перенаправление для решения этих проблем.

Загрузка и тестирование частных двоичных файлов

Правила, которые следует загрузчику DLL, гарантируют, что системные библиотеки DLL загружаются из системных расположений Windows, например в системной папке (%SystemRoot%\system32). Эти правила избегают атак посадки: где злоумышленник помещает код, который они написали в расположении, в котором они могут написать, а затем убедить некоторый процесс загрузить и выполнить его. Но правила загрузчика также затрудняют работу с компонентами ОС, так как для их запуска требуется обновление системы; и это очень сильное изменение.

Но вы можете использовать перенаправление для загрузки частных копий БИБЛИОТЕК DLL (например, для тестирования или измерения влияния на производительность изменения кода).

Если вы хотите внести свой вклад в исходный код в общедоступном репозитории GitHub WindowsAppSDK , необходимо протестировать изменения. И, опять же, это сценарий, для которого можно использовать перенаправление для загрузки частных копий БИБЛИОТЕК DLL вместо версий, которые поставляются с пакетом SDK для приложений Windows.

Параметры

На самом деле существует два способа убедиться, что приложение использует версию библиотеки DLL, которую вы хотите:

Совет

Если вы разработчик или администратор, следует использовать перенаправление БИБЛИОТЕК DLL для существующих приложений. Это связано с тем, что это не требует каких-либо изменений в самом приложении. Но если вы создаете новое приложение или обновляете существующее приложение, и вы хотите изолировать приложение от потенциальных проблем, создайте параллельный компонент.

Необязательно. Настройка реестра

Чтобы включить перенаправление БИБЛИОТЕК DLL на компьютере, необходимо создать новое значение реестра. В разделе ключа HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Optionsсоздайте новое значение DWORD с именем DevOverrideEnable. Задайте значение 1 и перезагрузите компьютер. Или используйте приведенную ниже команду (и перезагрузите компьютер).

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options" /v DevOverrideEnable /t REG_DWORD /d 1

При использовании этого набора значений реестра перенаправление DLL DotLocal учитывается, даже если приложение имеет манифест приложения.

Создание файла или папки перенаправления

Чтобы использовать перенаправление библиотеки DLL, вы создадите файл перенаправления или папку перенаправления (в зависимости от типа приложения), как показано в последующих разделах этого раздела.

Перенаправление библиотек DLL для упакованных приложений

Упаковаированное приложение требует специальной структуры папок для перенаправления БИБЛИОТЕК DLL. Следующий путь заключается в том, где загрузчик будет выглядеть при включении перенаправления:

<Drive>:\<path_to_package>\microsoft.system.package.metadata\application.local\

Если вы можете изменить .vcxproj файл, удобный способ создать и развернуть специальную папку с пакетом— добавить дополнительные шаги в сборку в вашей .vcxprojсборке:

<ItemDefinitionGroup>
    <PreBuildEvent>
        <Command>
            del $(FinalAppxManifestName) 2&gt;nul
            <!-- [[Using_.local_(DotLocal)_with_a_packaged_app]] This makes the extra DLL deployed via F5 get loaded instead of the system one. -->
            if NOT EXIST $(IntDir)\microsoft.system.package.metadata\application.local MKDIR $(IntDir)\microsoft.system.package.metadata\application.local
            if EXIST "&lt;A.dll&gt;" copy /y "&lt;A.dll&gt;" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
            if EXIST "&lt;B.dll&gt;" copy /y "&lt;B.dll&gt;" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
        </Command>
    </PreBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
    <!-- Include any locally built system experience -->
    <Media Include="$(IntDir)\microsoft.system.package.metadata\application.local\**">
        <Link>microsoft.system.package.metadata\application.local</Link>
    </Media>
</ItemGroup>

Давайте рассмотрим некоторые действия этой конфигурации.

  1. PreBuildEvent Настройте среду для запуска Visual Studio без отладки (или запуска отладки).

    <ItemDefinitionGroup>
      <PreBuildEvent>
    
  2. Убедитесь, что у вас есть правильная структура папок в промежуточном каталоге.

    <!-- [[Using_.local_(DotLocal)_with_modern_apps]] This makes the extra DLL deployed via Start get loaded instead of the system one. -->
    if NOT EXIST $(IntDir)\microsoft.system.package.metadata\application.local MKDIR $(IntDir)\microsoft.system.package.metadata\application.local
    
  3. Скопируйте все библиотеки DLL, созданные локально (и хотите использовать в предпочтениях библиотек DLL, развернутых системой) в application.local каталог. Вы можете выбрать библиотеки DLL примерно в любом месте (мы рекомендуем использовать доступные макросы для ваших .vcxproj). Просто убедитесь, что эти библиотеки DLL создаются до этого проекта; в противном случае они будут отсутствуют. Здесь показаны две команды копирования шаблонов ; используйте столько, сколько вам нужно, и измените <path-to-local-dll> заполнители.

      if EXIST "<path-to-local-dll>" copy /y "<path-to-local-dll>" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
      if EXIST "<path-to-local-dll>" copy /y "<path-to-local-dll>" $(IntDir)\microsoft.system.package.metadata\application.local 2&gt;nul
      </Command>
    </PreBuildEvent>
    
  4. Наконец, укажите, что необходимо включить специальный каталог и его содержимое в развернутый пакет.

    <ItemGroup>
      <!-- Include any locally built system experience -->
      <Media Include="$(IntDir)\microsoft.system.package.metadata\application.local\**">
        <Link>microsoft.system.package.metadata\application.local</Link>
      </Media>
    </ItemGroup>
    

Описанный здесь подход (с использованием промежуточного каталога) обеспечивает очистку системы управления исходным кодом и снижает вероятность случайного фиксации скомпилированного двоичного файла.

Далее необходимо выполнить развертывание проекта (повторно). Чтобы получить чистое (повторное)развертывание, может потребоваться удалить или очистить существующее развертывание на целевом устройстве.

Копирование двоичных файлов вручную

Если вы не можете использовать ваш .vcxproj способ, показанный выше, то вы можете достичь тех же окончания вручную на целевом устройстве с помощью нескольких простых шагов.

  1. Определите папку установки пакета. Это можно сделать в PowerShell, выпустив команду Get-AppxPackageи найдите возвращенное приложение InstallLocation .

  2. Используйте installLocation, чтобы изменить списки управления доступом, чтобы позволить себе создавать папки или копировать файлы. Измените <InstallLocation> заполнители в этом скрипте и запустите скрипт:

    cd <InstallLocation>\Microsoft.system.package.metadata
    takeown /F . /A
    icacls  . /grant Administrators:F
    md <InstallLocation>\Microsoft.system.package.metadata\application.local
    
  3. Наконец, вручную скопируйте все библиотеки DLL, созданные локально (и хотите использовать в предпочтениях для развернутых системой библиотек DLL) в application.local каталог и [повторно]запустите приложение.

Убедитесь, что все работало

Чтобы убедиться, что в среде выполнения загружается правильная библиотека DLL, можно использовать Visual Studio с подключенным отладчиком.

  1. Откройте окно модулей (отладка>модулей Windows).>
  2. Найдите библиотеку DLL и убедитесь, что путь указывает перенаправленную копию, а не версию, развернутую системой.
  3. Убедитесь, что загружается только одна копия заданной библиотеки DLL.

Как перенаправить библиотеки DLL для распакованных приложений

Файл перенаправления должен быть назван <your_app_name>.local. Таким образом, если имя вашего приложения равно Editor.exe, то присвойте файл Editor.exe.localперенаправления. Необходимо установить файл перенаправления в папку исполняемого файла. Необходимо также установить библиотеки DLL в папке исполняемого файла.

Содержимое файла перенаправления игнорируется. Его присутствие только приводит к тому, что загрузчик DLL проверка папку исполняемого файла сначала при загрузке библиотеки DLL. Чтобы устранить проблему COM, перенаправление применяется как к полному пути, так и к частичной загрузке имен. Поэтому перенаправление происходит в com-случае, а также независимо от пути, указанного в LoadLibrary или LoadLibraryEx. Если библиотека DLL не найдена в папке исполняемого файла, загрузка выполняется в обычном порядке поиска. Например, если приложение C:\myapp\myapp.exe вызывает LoadLibrary , используя следующий путь:

C:\Program Files\Common Files\System\mydll.dll

И если оба C:\myapp\myapp.exe.local и C:\myapp\mydll.dll существуют, загружается C:\myapp\mydll.dllLoadLibrary. В противном случае загрузка LoadLibrary .C:\Program Files\Common Files\System\mydll.dll

Кроме того, если имя C:\myapp\myapp.exe.local папки существует и содержитсяmydll.dll, загружается C:\myapp\myapp.exe.local\mydll.dllLoadLibrary.

Если вы используете перенаправление БИБЛИОТЕК DLL, а приложение не имеет доступа ко всем дискам и каталогам в порядке поиска, то LoadLibrary перестает выполнять поиск сразу после того, как доступ будет запрещен. Если вы не используете перенаправление библиотек DLL, loadLibrary пропускает каталоги, к которым он не может получить доступ, а затем продолжает поиск.

Рекомендуется установить библиотеки DLL приложений в той же папке, которая содержит приложение; даже если вы не используете перенаправление БИБЛИОТЕК DLL. Это гарантирует, что установка приложения не перезаписывает другие копии библиотеки DLL (тем самым вызывая сбой других приложений). Кроме того, если вы следуйте этой рекомендации, другие приложения не перезаписывают копию библиотеки DLL (и не вызывают сбой приложения).