Bertentangan dengan saran dari beberapa jawaban lain, penggunaan DllImport
atribut masih merupakan pendekatan yang benar.
Jujur saya tidak mengerti mengapa Anda tidak bisa melakukan seperti orang lain di dunia dan menentukan jalur relatif ke DLL Anda. Ya, jalur di mana aplikasi Anda akan diinstal berbeda pada komputer orang yang berbeda, tapi itu pada dasarnya aturan universal ketika datang ke penyebaran. The DllImport
Mekanisme dirancang dengan pikiran ini.
Bahkan, itu bahkan tidak DllImport
menanganinya. Ini adalah aturan pemuatan asli Win32 DLL yang mengatur berbagai hal, terlepas dari apakah Anda menggunakan pembungkus yang mudah ditangani (marshaller P / Invoke hanya menelepon LoadLibrary
). Aturan-aturan itu disebutkan dengan sangat rinci di sini , tetapi yang penting dikutip di sini:
Sebelum sistem mencari DLL, ia memeriksa yang berikut:
- Jika DLL dengan nama modul yang sama sudah dimuat dalam memori, sistem menggunakan DLL yang dimuat, tidak peduli di mana direktori itu berada. Sistem tidak mencari DLL.
- Jika DLL ada di daftar DLL yang dikenal untuk versi Windows di mana aplikasi berjalan, sistem menggunakan salinan DLL yang dikenal (dan DLL dependen DLL yang diketahui, jika ada). Sistem tidak mencari DLL.
Jika SafeDllSearchMode
diaktifkan (default), urutan pencarian adalah sebagai berikut:
- Direktori tempat aplikasi dimuat.
- Direktori sistem. Gunakan
GetSystemDirectory
fungsi untuk mendapatkan jalur direktori ini.
- Direktori sistem 16-bit. Tidak ada fungsi yang mendapatkan jalur direktori ini, tetapi sedang dicari.
- Direktori Windows. Gunakan
GetWindowsDirectory
fungsi untuk mendapatkan jalur direktori ini.
- Direktori saat ini.
- Direktori yang tercantum dalam
PATH
variabel lingkungan. Perhatikan bahwa ini tidak termasuk jalur per-aplikasi yang ditentukan oleh kunci registri App Paths. Kunci App Paths tidak digunakan saat menghitung jalur pencarian DLL.
Jadi, kecuali jika Anda menamai DLL Anda dengan hal yang sama dengan DLL sistem (yang seharusnya tidak Anda lakukan, dalam keadaan apa pun), urutan pencarian default akan mulai mencari di direktori tempat aplikasi Anda dimuat. Jika Anda menempatkan DLL di sana selama instalasi, itu akan ditemukan. Semua masalah rumit hilang jika Anda hanya menggunakan jalur relatif.
Tulis saja:
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Tetapi jika itu tidak berhasil karena alasan apa pun, dan Anda perlu memaksa aplikasi untuk mencari di direktori lain untuk DLL, Anda dapat memodifikasi jalur pencarian default menggunakan SetDllDirectory
fungsi .
Perhatikan bahwa, sesuai dokumentasi:
Setelah menelepon SetDllDirectory
, jalur pencarian DLL standar adalah:
- Direktori tempat aplikasi dimuat.
- Direktori ditentukan oleh
lpPathName
parameter.
- Direktori sistem. Gunakan
GetSystemDirectory
fungsi untuk mendapatkan jalur direktori ini.
- Direktori sistem 16-bit. Tidak ada fungsi yang mendapatkan jalur direktori ini, tetapi sedang dicari.
- Direktori Windows. Gunakan
GetWindowsDirectory
fungsi untuk mendapatkan jalur direktori ini.
- Direktori yang tercantum dalam
PATH
variabel lingkungan.
Jadi, selama Anda memanggil fungsi ini sebelum Anda memanggil fungsi yang diimpor dari DLL untuk pertama kalinya, Anda dapat memodifikasi jalur pencarian default yang digunakan untuk menemukan DLL. Manfaatnya, tentu saja, adalah Anda dapat memberikan nilai dinamis ke fungsi ini yang dihitung pada saat dijalankan. Itu tidak mungkin dengan DllImport
atribut, jadi Anda masih akan menggunakan jalur relatif (hanya nama DLL) di sana, dan bergantung pada urutan pencarian baru untuk menemukannya untuk Anda.
Anda harus P / Aktifkan fungsi ini. Deklarasi terlihat seperti ini:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);