Delen via


Dynamische koppelingsbibliotheekomleiding

Het DLL-laadprogramma is het onderdeel van het besturingssysteem dat verwijzingen naar DLL's oplost, laadt en koppelt. Dll-omleiding (Dynamic-Link Library) is een van de technieken waarmee u het gedrag van het DLL-laadprogrammakunt beïnvloeden en kunt bepalen welke van een van de verschillende kandidaat-DLL's het daadwerkelijk laadt.

Andere namen voor deze functie zijn .local, Dot Local, DotLocalen Dot Local Debugging.

Problemen met DLL-versiebeheer

Als uw toepassing afhankelijk is van een specifieke versie van een gedeelde DLL en een andere toepassing wordt geïnstalleerd met een nieuwere of oudere versie van die DLL, kan dit compatibiliteitsproblemen en instabiliteit veroorzaken; dit kan ertoe leiden dat uw app mislukt.

Het DLL-laadprogramma zoekt in de map waaruit het aanroepende proces is geladen (de map van het uitvoerbare bestand) voordat het op andere bestandssysteemlocaties wordt weergegeven. Een tijdelijke oplossing is het installeren van het DLL-bestand dat uw app nodig heeft in de map van het uitvoerbare bestand. Dat maakt het DLL-bestand effectief privé.

Maar dat lost het probleem voor COM niet op. Er kunnen twee niet-compatibele versies van een COM-server worden geïnstalleerd en geregistreerd (zelfs op verschillende bestandssysteemlocaties), maar er is slechts één plaats om de COM-server te registreren. Dus alleen de meest recente geregistreerde COM-server wordt geactiveerd.

U kunt omleiding gebruiken om deze problemen op te lossen.

Persoonlijke binaire bestanden laden en testen

De regels die het DLL-laadprogramma volgt, zorgen ervoor dat systeem-DLL's worden geladen vanaf de Windows-systeemlocaties, bijvoorbeeld de systeemmap (%SystemRoot%\system32). Deze regels voorkomen aanvallen: waarbij een kwaadwillende persoon code plaatst die ze op een locatie hebben geschreven waarnaar ze kunnen schrijven, en vervolgens een bepaald proces overtuigen om het te laden en uit te voeren. Maar de regels van het laadprogramma maken het ook moeilijker om te werken aan onderdelen van het besturingssysteem, omdat om ze uit te voeren het systeem moet worden bijgewerkt; en dat is een zeer impactvolle verandering.

U kunt echter omleiding gebruiken om privékopieën van DLL's te laden (voor doeleinden zoals testen of het meten van de invloed van de prestaties van een codewijziging).

Als u wilt bijdragen aan de broncode in de openbare WindowsAppSDK GitHub-opslagplaats, wilt u uw wijzigingen testen. En nogmaals, dat is een scenario waarvoor u omleiding kunt gebruiken om uw persoonlijke kopieën van DLL's te laden in plaats van de versies die worden verzonden met de Windows App SDK.

Uw opties

Er zijn zelfs twee manieren om ervoor te zorgen dat uw app gebruikmaakt van de versie van het DLL-bestand dat u wilt gebruiken:

Fooi

Als u een ontwikkelaar of beheerder bent, moet u DLL-omleiding gebruiken voor bestaande toepassingen. Dat komt doordat er geen wijzigingen in de app zelf nodig zijn. Maar als u een nieuwe app maakt of een bestaande app bijwerkt en u uw app wilt isoleren van potentiële problemen, maakt u een side-by-side-onderdeel.

Optioneel: het register configureren

Als u dll-omleidingscomputers wilt inschakelen, moet u een nieuwe registerwaarde maken. Maak onder de sleutel HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Optionseen nieuwe DWORD--waarde met de naam DevOverrideEnable. Stel de waarde in op 1 en start de computer opnieuw op. Of gebruik de onderstaande opdracht (en start de computer opnieuw op).

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

Wanneer deze registerwaarde is ingesteld, wordt dotLocal DLL-omleiding gerespecteerd, zelfs als de app een toepassingsmanifest heeft.

Een omleidingsbestand of -map maken

Als u DLL-omleiding wilt gebruiken, maakt u een omleidingsbestand of een omleidingsmap (afhankelijk van het type app dat u hebt), zoals in latere secties in dit onderwerp wordt weergegeven.

DLL's omleiden voor verpakte apps

Een verpakte app vereist een speciale mapstructuur voor DLL-omleiding. Het volgende pad is waar het laadprogramma eruitziet wanneer omleiding is ingeschakeld:

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

Als u het .vcxproj-bestand kunt bewerken, kunt u ervoor zorgen dat die speciale map wordt gemaakt en geïmplementeerd met uw pakket door enkele extra stappen toe te voegen aan de build in uw .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>

Laten we eens een aantal van de functies van die configuratie doorlopen.

  1. Stel een PreBuildEvent in voor uw Ervaring met Visual Studio Start Without Debugging (of Start Debugging) .

    <ItemDefinitionGroup>
      <PreBuildEvent>
    
  2. Zorg ervoor dat u de juiste mapstructuur in uw tussenliggende map hebt.

    <!-- [[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. Kopieer alle DLL's die u lokaal hebt gemaakt (en die u wilt gebruiken in voorkeur voor de door het systeem geïmplementeerde DLL's) in de application.local map. U kunt DLL's vanaf bijna elke locatie ophalen (we raden u aan de beschikbare macro's voor uw .vcxprojte gebruiken). Zorg ervoor dat deze DLL's worden gebouwd voordat dit project dat doet; anders ontbreken ze. Twee sjabloon kopieeropdrachten worden hier weergegeven; gebruik zoveel als u nodig hebt en bewerk de <path-to-local-dll> tijdelijke aanduidingen.

      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. Geef ten slotte aan dat u de speciale map en de inhoud ervan wilt opnemen in het geïmplementeerde pakket.

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

De methode die hier wordt beschreven (met behulp van een tussenliggende map) houdt uw broncodebeheer opgeruimd en vermindert de mogelijkheid om per ongeluk een gecompileerd binair bestand vast te leggen.

Vervolgens hoeft u alleen maar uw project (opnieuw) te implementeren. Als u een schone, volledige (her)implementatie wilt krijgen, moet u mogelijk ook de bestaande implementatie op uw doelapparaat verwijderen/opschonen.

De binaire bestanden handmatig kopiëren

Als u uw .vcxproj niet kunt gebruiken zoals hierboven wordt weergegeven, kunt u met een paar eenvoudige stappen hetzelfde eind bereiken op uw doelapparaat.

  1. Bepaal de installatiemap van het pakket. U kunt dit doen in PowerShell door de opdracht Get-AppxPackageuit te geven en te zoeken naar de InstallLocation- die wordt geretourneerd.

  2. Gebruik dat InstallLocation- om de ACL's te wijzigen zodat u mappen/bestanden kunt kopiëren. Bewerk de tijdelijke aanduidingen <InstallLocation> in dit script en voer het script uit:

    cd <InstallLocation>\Microsoft.system.package.metadata
    takeown /F . /A
    icacls  . /grant Administrators:F
    md <InstallLocation>\Microsoft.system.package.metadata\application.local
    
  3. Ten slotte kopieert u handmatig alle DLL's die u lokaal hebt gemaakt (en wilt gebruiken in voorkeur voor de door het systeem geïmplementeerde DLL's) naar de application.local map en start u de app [opnieuw].

Controleren of alles heeft gewerkt

Als u wilt controleren of de juiste DLL tijdens runtime wordt geladen, kunt u Visual Studio gebruiken met het bijgevoegde foutopsporingsprogramma.

  1. Open het venster Modules (Fouten opsporen>Windows>Modules).
  2. Zoek het DLL-bestand en zorg ervoor dat het pad de omgeleide kopie aangeeft en niet de door het systeem geïmplementeerde versie.
  3. Controleer of slechts één kopie van een opgegeven DLL is geladen.

DLL's omleiden voor uitgepakte apps

Het omleidingsbestand moet de naam <your_app_name>.localhebben. Dus als de naam van uw app Editor.exeis, noemt u het omleidingsbestand Editor.exe.local. U moet het omleidingsbestand installeren in de map van het uitvoerbare bestand. U moet ook de DLL's installeren in de map van het uitvoerbare bestand.

De inhoud van een omleidingsbestand wordt genegeerd; de aanwezigheid alleen zorgt ervoor dat het DLL-laadprogramma eerst de map van het uitvoerbare bestand controleert wanneer er een DLL wordt geladen. Om het COM-probleem te verhelpen, is deze omleiding van toepassing op zowel volledig pad als gedeeltelijke naam laden. Omleiding vindt dus plaats in het COM-geval en ook ongeacht het pad dat is opgegeven voor LoadLibrary- of LoadLibraryEx. Als het DLL-bestand niet wordt gevonden in de map van het uitvoerbare bestand, volgt het laden de gebruikelijke zoekvolgorde. Als de app bijvoorbeeld C:\myapp\myapp.exeLoadLibrary aanroept met behulp van het volgende pad:

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

En als zowel C:\myapp\myapp.exe.local als C:\myapp\mydll.dll bestaan, LoadLibraryC:\myapp\mydll.dllladen. Anders wordt LoadLibraryC:\Program Files\Common Files\System\mydll.dllgeladen.

Als er ook een map met de naam C:\myapp\myapp.exe.local bestaat en deze mydll.dllbevat, LoadLibraryC:\myapp\myapp.exe.local\mydll.dlllaadt.

Als u DLL-omleiding gebruikt en de app geen toegang heeft tot alle stations en mappen in de zoekvolgorde, LoadLibrary stopt met zoeken zodra de toegang is geweigerd. Als u geen met behulp van DLL-omleiding, slaat LoadLibrary mappen over die niet toegankelijk zijn en blijft het zoeken.

Het is raadzaam om app-DLL's te installeren in dezelfde map die de app bevat; zelfs als u geen DLL-omleiding gebruikt. Dit zorgt ervoor dat de installatie van de app geen andere kopieën van het DLL-bestand overschrijft (waardoor andere apps mislukken). Als u deze goede procedure volgt, overschrijft andere apps uw kopie van het DLL-bestand niet (en laat uw app niet mislukken).