Pengalihan pustaka tautan dinamis

Loader DLL adalah bagian dari sistem operasi (OS) yang menyelesaikan referensi ke DLL, memuatnya, dan menautkannya. Pengalihan pustaka tautan dinamis (DLL) adalah salah satu teknik di mana Anda dapat memengaruhi perilaku pemuat DLL, dan mengontrol salah satu dari beberapa DLL kandidat mana yang benar-benar dimuatnya.

Nama lain untuk fitur ini termasuk .local, Dot Local, DotLocal, dan Dot Local Debugging.

Masalah penerapan versi DLL

Jika aplikasi Anda bergantung pada versi tertentu dari DLL bersama, dan aplikasi lain diinstal dengan versi DLL yang lebih baru atau lebih lama, maka itu dapat menyebabkan masalah kompatibilitas dan ketidakstabilan; ini dapat menyebabkan aplikasi Anda mulai gagal.

Pemuat DLL mencari di folder tempat proses panggilan dimuat dari (folder yang dapat dieksekusi) sebelum terlihat di lokasi sistem file lainnya. Jadi salah satu solusinya adalah menginstal DLL yang dibutuhkan aplikasi Anda di folder executable Anda. Itu secara efektif membuat DLL privat.

Tetapi itu tidak menyelesaikan masalah untuk COM. Dua versi server COM yang tidak kompatibel dapat diinstal dan didaftarkan (bahkan di lokasi sistem file yang berbeda), tetapi hanya ada satu tempat untuk mendaftarkan server COM. Jadi hanya server COM terbaru yang terdaftar yang akan diaktifkan.

Anda dapat menggunakan pengalihan untuk menyelesaikan masalah ini.

Memuat dan menguji biner privat

Aturan yang diikuti pemuat DLL memastikan bahwa DLL sistem dimuat dari lokasi sistem Windows—misalnya, folder sistem (%SystemRoot%\system32). Aturan tersebut menghindari serangan penanaman: di mana musuh menempatkan kode yang mereka tulis di lokasi yang dapat mereka tulis, dan kemudian meyakinkan beberapa proses untuk memuat dan mengeksekusinya. Tetapi aturan loader juga membuatnya lebih sulit untuk bekerja pada komponen OS, karena untuk menjalankannya memerlukan pembaruan sistem; dan itu adalah perubahan yang sangat berdampak.

Tetapi Anda dapat menggunakan pengalihan untuk memuat salinan privat DLL (untuk tujuan seperti pengujian, atau mengukur dampak performa perubahan kode).

Jika Anda ingin berkontribusi pada kode sumber di repositori GitHub WindowsAppSDK publik, maka Anda harus menguji perubahan Anda. Dan, sekali lagi, itu adalah skenario di mana Anda dapat menggunakan pengalihan untuk memuat salinan DLL privat Anda alih-alih versi yang dikirim dengan SDK Aplikasi Windows.

Opsi Anda

Bahkan, ada dua cara untuk memastikan bahwa aplikasi Anda menggunakan versi DLL yang Anda inginkan:

Tip

Jika Anda adalah pengembang atau administrator, maka Anda harus menggunakan pengalihan DLL untuk aplikasi yang ada. Itu karena tidak memerlukan perubahan apa pun pada aplikasi itu sendiri. Tetapi jika Anda membuat aplikasi baru, atau memperbarui aplikasi yang ada, dan Ingin mengisolasi aplikasi dari potensi masalah, buat komponen berdampingan.

Opsional: mengonfigurasi registri

Untuk mengaktifkan pengalihan DLL di seluruh komputer, Anda harus membuat nilai registri baru. Di bawah kunci HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options, buat nilai DWORD baru dengan nama DevOverrideEnable. Atur nilai ke 1, dan mulai ulang komputer Anda. Atau gunakan perintah di bawah ini (dan mulai ulang komputer Anda).

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

Dengan kumpulan nilai registri tersebut, pengalihan DLL DotLocal dihormati meskipun aplikasi memiliki manifes aplikasi.

Membuat file atau folder pengalihan

Untuk menggunakan pengalihan DLL, Anda akan membuat file pengalihan atau folder pengalihan (tergantung jenis aplikasi yang Anda miliki), seperti yang akan kita lihat di bagian selanjutnya dalam topik ini.

Cara mengalihkan DLL untuk aplikasi paket

Aplikasi paket memerlukan struktur folder khusus untuk pengalihan DLL. Jalur berikut adalah tempat loader akan terlihat saat pengalihan diaktifkan:

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

Jika Anda dapat mengedit .vcxproj file, maka cara mudah untuk menyebabkan folder khusus tersebut dibuat dan disebarkan dengan paket Anda adalah dengan menambahkan beberapa langkah tambahan ke build di :.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>

Mari kita telusuri beberapa apa yang dilakukan konfigurasi tersebut.

  1. Siapkan PreBuildEvent untuk pengalaman Visual Studio Start Without Debugging (atau Start Debugging).

    <ItemDefinitionGroup>
      <PreBuildEvent>
    
  2. Pastikan Anda memiliki struktur folder yang benar di direktori perantara Anda.

    <!-- [[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. Salin DLL apa pun yang telah Anda buat secara lokal (dan ingin menggunakan preferensi ke DLL yang disebarkan sistem) ke application.local dalam direktori. Anda dapat mengambil DLL dari mana saja (kami sarankan Anda menggunakan makro yang tersedia untuk Anda .vcxproj). Pastikan BAHWA DLL tersebut dibangun sebelum proyek ini; jika tidak, mereka akan hilang. Dua perintah salin templat ditampilkan di sini; gunakan sebanyak yang Anda butuhkan, dan edit <path-to-local-dll> tempat penampung.

      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. Terakhir, tunjukkan bahwa Anda ingin menyertakan direktori khusus dan kontennya dalam paket yang disebarkan.

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

Pendekatan yang dijelaskan di sini (menggunakan direktori perantara) menjaga pendaftaran kontrol kode sumber Anda tetap bersih, dan mengurangi kemungkinan melakukan biner yang dikompilasi secara tidak sengaja.

Selanjutnya, yang perlu Anda lakukan adalah (kembali) menyebarkan proyek Anda. Untuk mendapatkan penyebaran yang bersih dan penuh (re), Anda mungkin juga harus menghapus instalan/membersihkan penyebaran yang ada pada perangkat target Anda.

Menyalin biner secara manual

Jika Anda tidak dapat menggunakan .vcxproj cara yang ditunjukkan di atas, maka Anda dapat mencapai ujung yang sama dengan tangan pada perangkat target Anda dengan beberapa langkah sederhana.

  1. Tentukan folder penginstalan paket. Anda dapat melakukannya di PowerShell dengan mengeluarkan perintah Get-AppxPackage, dan mencari InstallLocation yang dikembalikan.

  2. Gunakan InstallLocation tersebut untuk mengubah ACL agar Anda dapat membuat folder/menyalin file. <InstallLocation> Edit tempat penampung dalam skrip ini, dan jalankan skrip:

    cd <InstallLocation>\Microsoft.system.package.metadata
    takeown /F . /A
    icacls  . /grant Administrators:F
    md <InstallLocation>\Microsoft.system.package.metadata\application.local
    
  3. Terakhir, salin DLL apa pun yang telah Anda buat secara lokal (dan ingin menggunakan preferensi ke DLL yang disebarkan sistem) ke application.local direktori, dan [re]memulai aplikasi.

Verifikasi bahwa semuanya berfungsi

Untuk mengonfirmasi bahwa DLL yang benar sedang dimuat pada runtime, Anda dapat menggunakan Visual Studio dengan debugger terlampir.

  1. Buka jendela Modul (Debug>Modul Windows>).
  2. Temukan DLL, dan pastikan jalur menunjukkan salinan yang dialihkan, dan bukan versi yang disebarkan sistem.
  3. Konfirmasikan bahwa hanya satu salinan DLL tertentu yang dimuat.

Cara mengalihkan DLL untuk aplikasi yang tidak dikemas

File pengalihan harus bernama <your_app_name>.local. Jadi, jika nama aplikasi Anda adalah Editor.exe, beri nama file Editor.exe.localpengalihan Anda . Anda harus menginstal file pengalihan di folder yang dapat dieksekusi. Anda juga harus menginstal DLL di folder yang dapat dieksekusi.

Konten file pengalihan diabaikan; kehadirannya saja menyebabkan pemuat DLL memeriksa folder yang dapat dieksekusi terlebih dahulu setiap kali memuat DLL. Untuk mengurangi masalah COM, pengalihan tersebut berlaku untuk jalur lengkap dan pemuatan nama parsial. Jadi pengalihan terjadi dalam kasus COM dan juga terlepas dari jalur yang ditentukan ke LoadLibrary atau LoadLibraryEx. Jika DLL tidak ditemukan di folder executable, maka pemuatan mengikuti urutan pencarian yang biasa. Misalnya, jika aplikasi C:\myapp\myapp.exe memanggil LoadLibrary menggunakan jalur berikut:

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

Dan jika keduanya C:\myapp\myapp.exe.local dan C:\myapp\mydll.dll ada, maka LoadLibrary memuat C:\myapp\mydll.dll. Jika tidak, LoadLibrary memuat C:\Program Files\Common Files\System\mydll.dll.

Atau, jika folder bernama C:\myapp\myapp.exe.local ada, dan berisi mydll.dll, maka LoadLibrary memuat C:\myapp\myapp.exe.local\mydll.dll.

Jika Anda menggunakan pengalihan DLL, dan aplikasi tidak memiliki akses ke semua drive dan direktori dalam urutan pencarian, loadLibrary berhenti mencari segera setelah akses ditolak. Jika Anda tidak menggunakan pengalihan DLL, maka LoadLibrary melewati direktori yang tidak dapat diaksesnya, lalu melanjutkan pencarian.

Adalah praktik yang baik untuk menginstal DLL aplikasi di folder yang sama yang berisi aplikasi; bahkan jika Anda tidak menggunakan pengalihan DLL. Itu memastikan bahwa menginstal aplikasi tidak menimpa salinan DLL lainnya (sehingga menyebabkan aplikasi lain gagal). Selain itu, jika Anda mengikuti praktik yang baik ini, aplikasi lain tidak menimpa salinan DLL Anda (dan tidak menyebabkan aplikasi Anda gagal).