Dela via


Omdirigering av dynamiskt länkbibliotek

Den DLL-inläsaren är den del av operativsystemet (OS) som löser referenser till DLL:er, läser in dem och länkar dem. DLL-omdirigering (Dynamic Link Library) är en av de tekniker som du kan använda för att påverka beteendet för DLL-inläsarenoch styra vilken av flera kandidat-DLL:er som faktiskt läses in.

Andra namn för den här funktionen är .local, Dot Local, DotLocaloch Dot Local Debugging.

Problem med DLL-versionshantering

Om ditt program är beroende av en specifik version av en delad DLL och ett annat program installeras med en nyare eller äldre version av DLL:n kan det orsaka kompatibilitetsproblem och instabilitet. det kan leda till att din app börjar misslyckas.

DLL-inläsaren ser ut i mappen som anropsprocessen lästes in från (den körbara mappen) innan den tittar på andra filsystemplatser. En lösning är därför att installera den DLL som din app behöver i mappen för den körbara filen. Det gör DLL:en privat.

Men det löser inte problemet för COM. Två inkompatibla versioner av en COM-server kan installeras och registreras (även på olika filsystemplatser), men det finns bara ett ställe att registrera COM-servern på. Därför aktiveras bara den senaste registrerade COM-servern.

Du kan använda omdirigering för att lösa dessa problem.

Läsa in och testa privata binärfiler

De regler som DLL-inläsaren följer ser till att system-DLL:er läses in från Windows-systemplatserna, till exempel systemmappen (%SystemRoot%\system32). Dessa regler undviker planteringsattacker: där en angripare lägger kod som de skrev på en plats som de kan skriva till och sedan övertygar någon process att läsa in och köra den. Men lastarens regler gör det också svårare att arbeta med OS-komponenter, eftersom det krävs en uppdatering av systemet för att köra dem. och det är en mycket effektfull förändring.

Men du kan använda omdirigering för att läsa in privata kopior av DLL:er (för ändamål som testning eller mätning av prestandapåverkan för en kodändring).

Om du vill bidra till källkoden i den offentliga WindowsAppSDK GitHub-lagringsplats vill du testa ändringarna. Och återigen är det ett scenario där du kan använda omdirigering för att läsa in dina privata kopior av DLL:er i stället för de versioner som levereras med Windows App SDK.

Dina alternativ

Det finns faktiskt två sätt att se till att din app använder den version av DLL:en som du vill att den ska:

Dricks

Om du är utvecklare eller administratör bör du använda DLL-omdirigering för befintliga program. Det beror på att det inte kräver några ändringar i själva appen. Men om du skapar en ny app eller uppdaterar en befintlig app och vill isolera din app från potentiella problem skapar du en komponent sida vid sida.

Valfritt: konfigurera registret

Om du vill aktivera DLL-omdirigering i hela datorn måste du skapa ett nytt registervärde. Under nyckeln HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Optionsskapar du ett nytt DWORD- värde med namnet DevOverrideEnable. Ange värdet till 1 och starta om datorn. Eller använd kommandot nedan (och starta om datorn).

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

Med den registervärdeuppsättningen respekteras DotLocal DLL-omdirigering även om appen har ett programmanifest.

Skapa en omdirigeringsfil eller mapp

Om du vill använda DLL-omdirigering skapar du en omdirigeringsfil eller en omdirigeringsmapp (beroende på vilken typ av app du har), som vi ser i senare avsnitt i det här avsnittet.

Så här omdirigerar du DLL:er för paketerade appar

En paketerad app kräver en särskild mappstruktur för DLL-omdirigering. Följande sökväg är där inläsaren kommer att titta när omdirigering är aktiverad:

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

Om du kan redigera din .vcxproj-fil är ett praktiskt sätt att skapa och distribuera den särskilda mappen med ditt paket att lägga till några extra steg i bygget i din .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>

Låt oss gå igenom en del av vad den konfigurationen gör.

  1. Konfigurera en PreBuildEvent för Visual Studio-Starta utan att felsöka (eller Starta felsökning) .

    <ItemDefinitionGroup>
      <PreBuildEvent>
    
  2. Kontrollera att du har rätt mappstruktur i den mellanliggande katalogen.

    <!-- [[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. Kopiera alla DLL:er som du har skapat lokalt (och som du vill använda i stället för systemdistribuerade DLL:er) till katalogen application.local. Du kan hämta DLL:er från nästan var som helst (vi rekommenderar att du använder tillgängliga makron för din .vcxproj). Se bara till att dessa DLL:er skapas innan det här projektet gör det. annars kommer de att saknas. Här visas två mallar kopieringskommandon. använd så många du behöver och redigera platshållarna för <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. Slutligen anger du att du vill inkludera specialkatalogen och dess innehåll i det distribuerade paketet.

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

Metoden som beskrivs här (med hjälp av en mellanliggande katalog) håller listan över källkodskontroll ren och minskar risken för att oavsiktligt genomföra en kompilerad binär fil.

Sedan behöver du bara distribuera projektet igen. För att få en ren, fullständig (om)distribution kan du också behöva avinstallera/rensa den befintliga distributionen på målenheten.

Kopiera binärfilerna manuellt

Om du inte kan använda din .vcxproj på det sätt som visas ovan kan du uppnå samma ändar för hand på målenheten med ett par enkla steg.

  1. Fastställa paketets installationsmapp. Du kan göra det i PowerShell genom att utfärda kommandot Get-AppxPackageoch leta efter InstallLocation- som returneras.

  2. Använd InstallLocation för att ändra ACL:er så att du kan skapa mappar/kopiera filer. Redigera <InstallLocation> platshållare i det här skriptet och kör skriptet:

    cd <InstallLocation>\Microsoft.system.package.metadata
    takeown /F . /A
    icacls  . /grant Administrators:F
    md <InstallLocation>\Microsoft.system.package.metadata\application.local
    
  3. Slutligen kopierar du manuellt alla DLL:er som du har skapat lokalt (och vill använda i stället för systemdistribuerade DLL:er) till katalogen application.local och [starta om]appen.

Kontrollera att allt fungerade

För att bekräfta att rätt DLL läses in vid körning kan du använda Visual Studio med felsökningsprogrammet kopplat.

  1. Öppna fönstret Moduler (Felsöka>Windows>-moduler).
  2. Leta upp DLL:en och kontrollera att Path anger den omdirigerade kopian och inte den systemdistribuerade versionen.
  3. Bekräfta att endast en kopia av en viss DLL läses in.

Så här omdirigerar du DLL:er för uppackade appar

Omdirigeringsfilen måste ha namnet <your_app_name>.local. Så om appens namn är Editor.exenamnger du omdirigeringsfilen Editor.exe.local. Du måste installera omdirigeringsfilen i den körbara mappen. Du måste också installera DLL:er i den körbara mappen.

Det innehållet av en omdirigeringsfil ignoreras. enbart dess närvaro gör att DLL-inläsaren kontrollerar mappen för den körbara filen först när den läser in en DLL. För att minimera COM-problemet gäller omdirigeringen både för fullständig sökväg och partiell namninläsning. Så omdirigering sker i COM-fallet och även oavsett vilken sökväg som anges för att LoadLibrary eller LoadLibraryEx. Om DLL-filen inte hittas i den körbara mappen följer inläsningen sin vanliga sökordning. Om appen till exempel C:\myapp\myapp.exe anropar LoadLibrary med hjälp av följande sökväg:

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

Och om både C:\myapp\myapp.exe.local och C:\myapp\mydll.dll finns läser LoadLibrary in C:\myapp\mydll.dll. Annars läser LoadLibrary in C:\Program Files\Common Files\System\mydll.dll.

Om det finns en mapp med namnet C:\myapp\myapp.exe.local och den innehåller mydll.dllläser LoadLibrary in C:\myapp\myapp.exe.local\mydll.dll.

Om du använder DLL-omdirigering och appen inte har åtkomst till alla enheter och kataloger i sökordningen slutar LoadLibrary söka så snart åtkomst nekas. Om du inte med DLL-omdirigering hoppar LoadLibrary över kataloger som den inte kan komma åt och sedan fortsätter sökningen.

Det är bra att installera app-DLL:er i samma mapp som innehåller appen. även om du inte använder DLL-omdirigering. Det säkerställer att installationen av appen inte skriver över andra kopior av DLL:en (vilket gör att andra appar misslyckas). Om du följer den här goda praxisen skriver andra appar inte över din kopia av DLL:en (och gör inte att appen misslyckas).