Freigeben über


Umleitung der Dynamic Link Library

Das DLL-Ladeprogramm ist teil des Betriebssystems (Os), das Verweise auf DLLs auflöst, lädt und verknüpft. Die Dll-Umleitung (Dynamic Link Library) ist eine der Techniken, mit denen Sie das Verhalten des DLL-Ladeprogrammbeeinflussen und steuern können, welche von mehreren Kandidaten-DLLs tatsächlich geladen werden.

Weitere Namen für dieses Feature sind .local, Dot Local, DotLocalund Dot Local Debugging.

Probleme mit der DLL-Versionsverwaltung

Wenn Ihre Anwendung von einer bestimmten Version einer freigegebenen DLL abhängt und eine andere Anwendung mit einer neueren oder älteren Version dieser DLL installiert wird, kann dies Kompatibilitätsprobleme und Instabilität verursachen; Die App kann dazu führen, dass die App fehlschlägt.

Das DLL-Ladeprogramm sucht in dem Ordner, aus dem der aufrufende Prozess (ordner der ausführbare Datei) geladen wurde, bevor er an anderen Dateisystemspeicherorten aussieht. Daher besteht eine Problemumgehung darin, die DLL zu installieren, die Ihre App im Ordner Ihrer ausführbaren Datei benötigt. Das macht die DLL effektiv privat.

Aber das löst das Problem für COM nicht. Zwei inkompatible Versionen eines COM-Servers können installiert und registriert werden (auch an verschiedenen Dateisystemspeicherorten), aber es gibt nur einen Ort zum Registrieren des COM-Servers. Daher wird nur der neueste registrierte COM-Server aktiviert.

Sie können die Umleitung verwenden, um diese Probleme zu lösen.

Laden und Testen privater Binärdateien

Die folgenden Regeln stellen sicher, dass System-DLLs aus den Windows-Systemspeicherorten geladen werden, z. B. den Systemordner (%SystemRoot%\system32). Diese Regeln vermeiden Pflanzungsangriffe: Wenn ein Angreifer Code platziert, den er an einem Ort geschrieben hat, in den er schreiben kann, und dann einen Prozess zum Laden und Ausführen davon überzeugen. Die Regeln des Ladegeräts erschweren aber auch die Arbeit an Betriebssystemkomponenten, da zum Ausführen des Systems eine Aktualisierung des Systems erforderlich ist; und das ist eine sehr wirkungsvolle Änderung.

Sie können jedoch die Umleitung verwenden, um private Kopien von DLLs zu laden (z. B. zum Testen oder Messen der Leistungsauswirkungen einer Codeänderung).

Wenn Sie am Quellcode im öffentlichen WindowsAppSDK GitHub-Repository mitwirken möchten, sollten Sie Ihre Änderungen testen. Und auch hier ist das ein Szenario, für das Sie die Umleitung verwenden können, um Ihre privaten Kopien von DLLs anstelle der Versionen zu laden, die mit dem Windows App SDK ausgeliefert werden.

Ihre Optionen

Tatsächlich gibt es zwei Möglichkeiten, um sicherzustellen, dass Ihre App die Version der DLL verwendet, für die Sie sie verwenden möchten:

Trinkgeld

Wenn Sie Entwickler oder Administrator sind, sollten Sie die DLL-Umleitung für vorhandene Anwendungen verwenden. Das liegt daran, dass keine Änderungen an der App selbst erforderlich sind. Wenn Sie jedoch eine neue App erstellen oder eine vorhandene App aktualisieren und Ihre App von potenziellen Problemen isolieren möchten, erstellen Sie eine parallele Komponente.

Optional: Konfigurieren der Registrierung

Um DIE DLL-Umleitung computerweit zu aktivieren, müssen Sie einen neuen Registrierungswert erstellen. Erstellen Sie unter dem Schlüssel HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Optionseinen neuen DWORD- Wert mit dem Namen DevOverrideEnable-. Legen Sie den Wert auf 1 fest, und starten Sie den Computer neu. Oder verwenden Sie den folgenden Befehl (und starten Sie den Computer neu).

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

Bei diesem Registrierungswertsatz wird die DotLocal-DLL-Umleitung berücksichtigt, auch wenn die App über ein Anwendungsmanifest verfügt.

Erstellen einer Umleitungsdatei oder eines Ordners

Um die DLL-Umleitung zu verwenden, erstellen Sie eine Umleitungsdatei oder einen Umleitungsordner (je nach App-Art), wie in späteren Abschnitten in diesem Thema zu sehen ist.

So leiten Sie DLLs für verpackte Apps um

Eine verpackte App erfordert eine spezielle Ordnerstruktur für die DLL-Umleitung. Der folgende Pfad ist der Ort, an dem das Ladeprogramm nachschaut, wenn die Umleitung aktiviert ist:

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

Wenn Sie Ihre .vcxproj Datei bearbeiten können, ist es eine bequeme Möglichkeit, diesen speziellen Ordner mit Ihrem Paket zu erstellen und mit Ihrem Paket zu bereitstellen, darin, dem Build in Ihrer .vcxprojeinige zusätzliche Schritte hinzuzufügen:

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

Sehen wir uns einige der Aktionen dieser Konfiguration an.

  1. Richten Sie eine PreBuildEvent für Visual Studio ein, "Ohne Debuggen starten" (oder "Debuggenstarten") einrichten.

    <ItemDefinitionGroup>
      <PreBuildEvent>
    
  2. Stellen Sie sicher, dass Sie über die richtige Ordnerstruktur in Ihrem Zwischenverzeichnis verfügen.

    <!-- [[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. Kopieren Sie alle DLLs, die Sie lokal erstellt haben (und vor allem für die vom System bereitgestellten DLLs verwenden möchten) in das verzeichnis application.local. Sie können DLLs von praktisch überall aus aufnehmen (es wird empfohlen, dass Sie die verfügbaren Makros für Ihre .vcxprojverwenden). Achten Sie einfach darauf, dass diese DLLs vor diesem Projekt erstellt werden; andernfalls fehlen sie. Hier werden zwei Vorlage Kopierbefehle angezeigt; verwenden Sie beliebig viele Platzhalter, und bearbeiten Sie die <path-to-local-dll> Platzhalter.

      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. Geben Sie abschließend an, dass Sie das spezielle Verzeichnis und dessen Inhalt in das bereitgestellte Paket einschließen möchten.

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

Der hier beschriebene Ansatz (unter Verwendung eines Zwischenverzeichnisses) sorgt dafür, dass die Liste der Quellcodeverwaltung sauber ist und die Möglichkeit reduziert wird, versehentlich ein kompiliertes Binärdatei-Commit zu übernehmen.

Als Nächstes müssen Sie lediglich Ihr Projekt erneut bereitstellen. Um eine saubere, vollständige (re)Bereitstellung zu erhalten, müssen Sie möglicherweise auch die vorhandene Bereitstellung auf Ihrem Zielgerät deinstallieren/bereinigen.

Manuelles Kopieren der Binärdateien

Wenn Sie Ihre .vcxproj nicht wie oben dargestellt verwenden können, können Sie dieselben Enden mit einigen einfachen Schritten auf Ihrem Zielgerät erreichen.

  1. Bestimmen Sie den Installationsordner des Pakets. Sie können dies in PowerShell tun, indem Sie den Befehl Get-AppxPackageausstellen und nach dem InstallLocation- suchen, das zurückgegeben wird.

  2. Verwenden Sie diese InstallLocation-, um die ACLs zu ändern, um sich selbst das Erstellen von Ordnern/Kopieren von Dateien zu ermöglichen. Bearbeiten Sie die <InstallLocation> Platzhalter in diesem Skript, und führen Sie das Skript aus:

    cd <InstallLocation>\Microsoft.system.package.metadata
    takeown /F . /A
    icacls  . /grant Administrators:F
    md <InstallLocation>\Microsoft.system.package.metadata\application.local
    
  3. Kopieren Sie schließlich manuell alle DLLs, die Sie lokal erstellt haben (und vor allem für die vom System bereitgestellten DLLs verwenden möchten) in das verzeichnis application.local, und starten Sie die App erneut.

Überprüfen, ob alles funktioniert hat

Um zu bestätigen, dass die richtige DLL zur Laufzeit geladen wird, können Sie Visual Studio mit dem angefügten Debugger verwenden.

  1. Öffnen Sie das Fenster module (Debug>Windows>Modules).
  2. Suchen Sie die DLL, und stellen Sie sicher, dass der Path die umgeleitete Kopie und nicht die vom System bereitgestellte Version angibt.
  3. Vergewissern Sie sich, dass nur eine Kopie einer bestimmten DLL geladen wird.

So leiten Sie DLLs für entpackte Apps um

Die Umleitungsdatei muss <your_app_name>.localbenannt werden. Wenn der Name Ihrer App also Editor.exeist, benennen Sie die Umleitungsdatei Editor.exe.local. Sie müssen die Umleitungsdatei im Ordner der ausführbaren Datei installieren. Sie müssen auch die DLLs im Ordner der ausführbaren Datei installieren.

Der Inhalt einer Umleitungsdatei wird ignoriert; Die Anwesenheit allein bewirkt, dass das DLL-Ladeprogramm zuerst den Ordner der ausführbaren Datei überprüft, wenn eine DLL geladen wird. Um das COM-Problem zu beheben, gilt diese Umleitung sowohl für das laden des vollständigen Pfads als auch für das teilweise Laden von Namen. Die Umleitung erfolgt also im COM-Fall und unabhängig vom Pfad, der LoadLibrary oder LoadLibraryEx-angegeben ist. Wenn die DLL nicht im Ordner der ausführbaren Datei gefunden wird, folgt das Laden der üblichen Suchreihenfolge. Wenn die App beispielsweise C:\myapp\myapp.exeLoadLibrary aufruft, unter Verwendung des folgenden Pfads:

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

Und wenn sowohl C:\myapp\myapp.exe.local als auch C:\myapp\mydll.dll vorhanden sind, wird LoadLibraryC:\myapp\mydll.dllgeladen. Andernfalls wird LoadLibraryC:\Program Files\Common Files\System\mydll.dllgeladen.

Wenn ein Ordner mit dem Namen C:\myapp\myapp.exe.local vorhanden ist und mydll.dllenthält, wird LoadLibraryC:\myapp\myapp.exe.local\mydll.dllgeladen.

Wenn Sie die DLL-Umleitung verwenden und die App keinen Zugriff auf alle Laufwerke und Verzeichnisse in der Suchreihenfolge hat, LoadLibrary die Suche beendet, sobald der Zugriff verweigert wird. Wenn Sie mit der DLL-Umleitung nicht werden, überspringt LoadLibrary Verzeichnisse, auf die er nicht zugreifen kann, und führt dann die Suche fort.

Es empfiehlt sich, App-DLLs im selben Ordner zu installieren, der die App enthält. auch wenn Sie keine DLL-Umleitung verwenden. Dadurch wird sichergestellt, dass die Installation der App keine anderen Kopien der DLL überschreibt (wodurch andere Apps fehlschlagen). Wenn Sie diese bewährte Methode befolgen, überschreiben andere Apps ihre Kopie der DLL nicht (und führen Sie nicht dazu, dass Ihre App fehlschlägt).