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:
- DLL-omleiding. Lees dit onderwerp verder voor meer informatie.
- Onderdelen naast elkaar. Beschreven in het onderwerp Geïsoleerde toepassingen en assembly's naast elkaar.
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 Options
een 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>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 "<A.dll>" copy /y "<A.dll>" $(IntDir)\microsoft.system.package.metadata\application.local 2>nul
if EXIST "<B.dll>" copy /y "<B.dll>" $(IntDir)\microsoft.system.package.metadata\application.local 2>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.
Stel een
PreBuildEvent
in voor uw Ervaring met Visual Studio Start Without Debugging (of Start Debugging) .<ItemDefinitionGroup> <PreBuildEvent>
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
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.vcxproj
te 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>nul if EXIST "<path-to-local-dll>" copy /y "<path-to-local-dll>" $(IntDir)\microsoft.system.package.metadata\application.local 2>nul </Command> </PreBuildEvent>
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.
Bepaal de installatiemap van het pakket. U kunt dit doen in PowerShell door de opdracht
Get-AppxPackage
uit te geven en te zoeken naar de InstallLocation- die wordt geretourneerd.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
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.
- Open het venster Modules (Fouten opsporen>Windows>Modules).
- Zoek het DLL-bestand en zorg ervoor dat het pad de omgeleide kopie aangeeft en niet de door het systeem geïmplementeerde versie.
- 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>.local
hebben. Dus als de naam van uw app Editor.exe
is, 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.exe
LoadLibrary 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.dll
laden. Anders wordt LoadLibraryC:\Program Files\Common Files\System\mydll.dll
geladen.
Als er ook een map met de naam C:\myapp\myapp.exe.local
bestaat en deze mydll.dll
bevat, LoadLibraryC:\myapp\myapp.exe.local\mydll.dll
laadt.
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).