Trái với những gợi ý của một số câu trả lời khác, sử dụng DllImport
thuộc tính vẫn là cách tiếp cận đúng.
Tôi thực sự không hiểu tại sao bạn không thể làm giống như mọi người khác trên thế giới và chỉ định một đường dẫn tương đối đến DLL của bạn. Đúng, đường dẫn ứng dụng của bạn sẽ được cài đặt khác nhau trên các máy tính của những người khác nhau, nhưng về cơ bản đó là một quy tắc chung khi triển khai. Các DllImport
cơ chế được thiết kế với điều này trong tâm trí.
Trong thực tế, nó thậm chí không DllImport
xử lý nó. Đó là quy tắc tải DLL Win32 bản địa chi phối mọi thứ, bất kể bạn có đang sử dụng trình bao bọc được quản lý tiện dụng hay không (P / Invoke marshaller chỉ gọi LoadLibrary
). Những quy tắc được liệt kê rất chi tiết ở đây , nhưng những quy tắc quan trọng được trích ở đây:
Trước khi hệ thống tìm kiếm một DLL, nó sẽ kiểm tra như sau:
- Nếu một DLL có cùng tên mô-đun đã được tải trong bộ nhớ, hệ thống sẽ sử dụng DLL được tải, bất kể nó nằm trong thư mục nào. Hệ thống không tìm kiếm DLL.
- Nếu DLL nằm trong danh sách các DLL đã biết cho phiên bản Windows mà ứng dụng đang chạy, thì hệ thống sẽ sử dụng bản sao của DLL đã biết (và DLL phụ thuộc của DLL đã biết, nếu có). Hệ thống không tìm kiếm DLL.
Nếu SafeDllSearchMode
được bật (mặc định), thứ tự tìm kiếm như sau:
- Thư mục mà ứng dụng được tải.
- Thư mục hệ thống. Sử dụng
GetSystemDirectory
chức năng để có được đường dẫn của thư mục này.
- Thư mục hệ thống 16 bit. Không có chức năng nào có được đường dẫn của thư mục này, nhưng nó được tìm kiếm.
- Thư mục Windows. Sử dụng
GetWindowsDirectory
chức năng để có được đường dẫn của thư mục này.
- Thư mục hiện tại.
- Các thư mục được liệt kê trong
PATH
biến môi trường. Lưu ý rằng điều này không bao gồm đường dẫn cho mỗi ứng dụng được chỉ định bởi khóa đăng ký Đường dẫn ứng dụng. Khóa Đường dẫn ứng dụng không được sử dụng khi tính toán đường dẫn tìm kiếm DLL.
Vì vậy, trừ khi bạn đặt tên DLL của bạn giống với DLL hệ thống (mà rõ ràng bạn không nên làm, trong mọi trường hợp), thứ tự tìm kiếm mặc định sẽ bắt đầu tìm trong thư mục mà ứng dụng của bạn được tải. Nếu bạn đặt DLL ở đó trong quá trình cài đặt, nó sẽ được tìm thấy. Tất cả các vấn đề phức tạp sẽ biến mất nếu bạn chỉ sử dụng các đường dẫn tương đối.
Chỉ viết:
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Nhưng nếu điều đó không hoạt động vì bất kỳ lý do gì và bạn cần buộc ứng dụng tìm trong một thư mục khác cho DLL, bạn có thể sửa đổi đường dẫn tìm kiếm mặc định bằng cách sử dụng SetDllDirectory
hàm .
Lưu ý rằng, theo tài liệu:
Sau khi gọi SetDllDirectory
, đường dẫn tìm kiếm DLL tiêu chuẩn là:
- Thư mục mà ứng dụng được tải.
- Thư mục được chỉ định bởi
lpPathName
tham số.
- Thư mục hệ thống. Sử dụng
GetSystemDirectory
chức năng để có được đường dẫn của thư mục này.
- Thư mục hệ thống 16 bit. Không có chức năng nào có được đường dẫn của thư mục này, nhưng nó được tìm kiếm.
- Thư mục Windows. Sử dụng
GetWindowsDirectory
chức năng để có được đường dẫn của thư mục này.
- Các thư mục được liệt kê trong
PATH
biến môi trường.
Vì vậy, miễn là bạn gọi hàm này trước khi bạn gọi hàm được nhập từ DLL lần đầu tiên, bạn có thể sửa đổi đường dẫn tìm kiếm mặc định được sử dụng để định vị DLL. Tất nhiên, lợi ích là bạn có thể chuyển một giá trị động cho hàm này được tính toán trong thời gian chạy. Điều đó là không thể với DllImport
thuộc tính, vì vậy bạn vẫn sẽ sử dụng một đường dẫn tương đối (chỉ tên của DLL) ở đó và dựa vào thứ tự tìm kiếm mới để tìm nó cho bạn.
Bạn sẽ phải P / Gọi chức năng này. Tuyên bố trông như thế này:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);