Redirection de bibliothèque de liens dynamiques

Le chargeur DLL fait partie du système d’exploitation qui résout les références aux DLL, les charge et les lie. La redirection de bibliothèque de liens dynamiques (DLL) est l’une des techniques par lesquelles vous pouvez influencer le comportement du chargeur DLL et contrôler l’une des DLL candidates qu’elle charge réellement.

Les autres noms de cette fonctionnalité incluent .local, Dot Local, DotLocal et Dot Local Debugging.

Problèmes de version DLL

Si votre application dépend d’une version spécifique d’une DLL partagée et qu’une autre application est installée avec une version plus récente ou plus ancienne de cette DLL, cela peut entraîner des problèmes de compatibilité et d’instabilité.

Le chargeur de DLL examine le dossier à partir duquel le processus appelant a été chargé (le dossier de l’exécutable) avant d’examiner d’autres emplacements du système de fichiers. Une solution consiste donc à installer la DLL dont votre application a besoin dans le dossier de votre exécutable. Cela rend la DLL effectivement privée.

Mais cela ne résout pas le problème pour COM. Deux versions incompatibles d’un serveur COM peuvent être installées et enregistrées (même dans des emplacements différents du système de fichiers), mais il n’y a qu’un seul emplacement où enregistrer le serveur COM. Ainsi, seul le dernier serveur COM inscrit sera activé.

Vous pouvez utiliser la redirection pour résoudre ces problèmes.

Chargement et test des fichiers binaires privés

Les règles que le chargeur DLL suit garantissent que les DLL système sont chargées à partir des emplacements système Windows, par exemple, le dossier système (%SystemRoot%\system32). Ces règles évitent les attaques de plantation : où un adversaire place du code qu’il a écrit dans un emplacement où il peut écrire, puis convaincre un processus de chargement et d’exécution. Mais les règles du chargeur rendent également plus difficile le travail sur les composants du système d’exploitation, car pour les faire fonctionner, il faut mettre à jour le système, ce qui constitue un changement très important.

Mais vous pouvez utiliser la redirection pour charger des copies privées de DLL (à des fins de test ou pour mesurer l’impact d’une modification du code sur le niveau de performance).

Si vous souhaitez contribuer au code source dans le référentiel GitHub WindowsAppSDK public, vous devez tester vos modifications. Il s’agit là encore d’un scénario pour lequel vous pouvez utiliser la redirection pour charger vos copies privées des DLL au lieu des versions livrées avec le Windows App SDK.

Vos options

En fait, il existe deux façons de s’assurer que votre application utilise la version de la DLL que vous souhaitez :

Conseil

Si vous êtes développeur ou administrateur, vous devez utiliser la redirection DLL pour les applications existantes. Cela est dû au fait qu’il ne nécessite aucune modification de l’application elle-même. Mais si vous créez une nouvelle application, ou si vous mettez à jour une application existante, et que vous souhaitez isoler votre application des problèmes potentiels, créez un composant côte à côte.

Facultatif : configurer le Registre

Pour activer la redirection DLL à l’échelle de la machine, vous devez créer une nouvelle valeur de Registre. Sous la clé HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options, créez une valeur DWORD avec le nom DevOverrideEnable. Définissez la valeur sur 1 et redémarrez votre ordinateur. Ou vous pouvez également utiliser la commande ci-dessous (et redémarrer votre ordinateur).

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

Avec ce jeu de valeurs de Registre, la redirection de DLL DotLocal est respectée même si l’application a un manifeste de l’application.

Créez un fichier ou un dossier de redirection

Pour utiliser la redirection DLL, vous allez créer un fichier de redirection ou un dossier de redirection (en fonction du type d’application que vous avez), comme nous le verrons dans les sections ultérieures de cette rubrique.

Guide pratique pour rediriger des DLL pour les applications empaquetées

Une application de package nécessite une structure de dossiers spéciale pour la redirection DLL. Le chemin d’accès suivant est l’emplacement où le chargeur recherche lorsque la redirection est activée :

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

Si vous pouvez modifier votre .vcxproj fichier, un moyen pratique de créer et de déployer ce dossier spécial avec votre package consiste à ajouter des étapes supplémentaires à la build dans votre .vcxprojfichier :

<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>

Évaluons certaines de ce que fait cette configuration.

  1. Configurez une PreBuildEvent expérience de démarrage sans débogage (ou démarrez le débogage) de Visual Studio.

    <ItemDefinitionGroup>
      <PreBuildEvent>
    
  2. Vérifiez que vous disposez de la structure de dossiers correcte dans votre répertoire intermédiaire.

    <!-- [[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. Copiez les DLL que vous avez créées localement (et souhaitez utiliser en préférence les DLL déployées par le système) dans le application.local répertoire. Vous pouvez récupérer des DLL à partir de n’importe où (nous vous recommandons d’utiliser les macros disponibles pour votre .vcxproj). Veillez simplement à ce que ces DLL soient générées avant que ce projet ne le fasse; sinon elles seront manquantes. Deux commandes de copie de modèle sont affichées ici; utilisez autant que nécessaire et modifiez les <path-to-local-dll> espaces réservés.

      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. Enfin, indiquez que vous souhaitez inclure le répertoire spécial et son contenu dans le package déployé.

    <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>
    

L’approche décrite ici (à l’aide d’un répertoire intermédiaire) conserve l’inscription de votre contrôle de code source propre et réduit la possibilité de valider accidentellement un binaire compilé.

Ensuite, il vous suffit de déployer ou de redéployer votre projet. Pour obtenir un déploiement propre, et un (e)déploiement complet, vous devrez peut-être également désinstaller/propre le déploiement existant sur votre périphérique cible.

Copie manuelle des fichiers binaires

Si vous n’êtes pas en mesure d’utiliser votre .vcxproj appareil comme indiqué ci-dessus, vous pouvez atteindre les mêmes extrémités en main sur votre périphérique cible avec quelques étapes simples.

  1. Déterminez le dossier d’installation du package. Vous pouvez le faire dans PowerShell en émettant la commande Get-AppxPackageet en recherchant l’InstallLocation retourné.

  2. Utilisez cet InstallLocation pour modifier les listes de contrôle d’accès pour vous permettre de créer des dossiers/copier des fichiers. Modifiez les <InstallLocation> espaces réservés dans ce script et exécutez le script :

    cd <InstallLocation>\Microsoft.system.package.metadata
    takeown /F . /A
    icacls  . /grant Administrators:F
    md <InstallLocation>\Microsoft.system.package.metadata\application.local
    
  3. Enfin, copiez manuellement toutes les DLL que vous avez créées localement (et que vous souhaitez utiliser de préférence aux DLL déployées par le système) dans le application.localrépertoire, et [re]démarrez l’application.

Vérifiez que tout a fonctionné

Pour vérifier que la DLL correcte est chargée au moment de l’exécution, vous pouvez utiliser Visual Studio avec le débogueur attaché.

  1. Ouvrez la fenêtre Modules (Déboguer>les modules >Windows).
  2. Recherchez la DLL et vérifiez que le chemin d’accès indique la copie redirigée, et non la version déployée par le système.
  3. Vérifiez qu’une seule copie d’une DLL donnée est chargée.

Guide pratique pour rediriger des DLL pour les applications qui ne sont pas en package

Le fichier de redirection doit être nommé <your_app_name>.local. Par conséquent, si le nom de votre application est Editor.exe, nommez votre fichier de redirectionEditor.exe.local. Vous devez installer le fichier de redirection dans le dossier de l’exécutable. Vous devez également installer les DLL dans le dossier de l’exécutable.

Le contenu d’un fichier de redirection est ignoré; sa présence seule entraîne le chargement de la DLL à case activée le dossier de l’exécutable dès qu’il charge une DLL. Pour atténuer le problème COM, cette redirection s’applique à la fois au chemin d’accès complet et au chargement partiel du nom. Par conséquent, la redirection se produit dans le cas COM et indépendamment du chemin d’accès spécifié à LoadLibrary ou LoadLibraryEx. Si la DLL est introuvable dans le dossier de l’exécutable, le chargement suit son ordre de recherche habituel. Par exemple, si l’application C:\myapp\myapp.exe appelle LoadLibrary à l’aide du chemin d’accès suivant :

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

Et si C:\myapp\myapp.exe.local et C:\myapp\mydll.dll existent à la fois, loadLibrary charge C:\myapp\mydll.dll. Sinon, LoadLibrary charge C:\Program Files\Common Files\System\mydll.dll.

Sinon, si un dossier nommé C:\myapp\myapp.exe.local existe et qu’il contientmydll.dll, puis loadLibrary se chargeC:\myapp\myapp.exe.local\mydll.dll.

Si vous utilisez la redirection DLL et que l’application n’a pas accès à tous les lecteurs et répertoires dans l’ordre de recherche, LoadLibrary cesse de rechercher dès que l’accès est refusé. Si vous n’utilisez pas la redirection DLL, LoadLibrary ignore les répertoires auxquels il ne peut pas accéder, puis continue la recherche.

Il est recommandé d’installer des DLL d’application dans le même dossier que celui contenant l’application; même si vous n’utilisez pas la redirection DLL. Cela garantit que l’installation de l’application ne remplace pas d’autres copies de la DLL (ce qui entraîne l’échec d’autres applications). En outre, si vous suivez cette bonne pratique, les autres applications ne remplacent pas votre copie de la DLL (et ne provoquent pas l’échec de votre application).