Вопреки предложениям некоторых других ответов, использование атрибута DllImport
по-прежнему является правильным.
Я честно не понимаю, почему вы не можете сделать так же, как все остальные в мире, и указать родственник путь к вашей DLL. Да, путь, в котором ваше приложение будет установлено, отличается на компьютерах разных людей, но это в основном универсальное правило, когда дело доходит до развертывания. Механизм DllImport
разработан с учетом этого.
Фактически, это даже не DllImport
, который обрабатывает его. Это правила загрузки загружаемых файлов Win32 DLL, которые управляют вещами, независимо от того, используете ли вы удобные управляемые обертки (маршаллер P/Invoke просто вызывает LoadLibrary
). Эти правила перечислены в деталях here, но важные из них взяты здесь:
перед системой поиска для DLL, он проверяет следующее:
- Если DLL с тем же имя модуля уже загружено в память, система использует загруженную DLL, независимо от того, в какой директории она находится. Система не ищет DLL.
- Если DLL находится в списке известных DLL для версии Windows, на которой работает приложение, система использует свою копию известной DLL (и известных DLL-зависимых библиотек DLL, если таковые имеются). Система не ищет DLL.
Если SafeDllSearchMode
включена (по умолчанию), порядок поиска выглядит следующим образом:
- каталог, из которого загружается приложение.
- Системный каталог. Используйте функцию
GetSystemDirectory
, чтобы получить путь к этому каталогу.
- 16-разрядный системный каталог. Нет функции, которая получает путь к этому каталогу, но выполняется поиск.
- Каталог Windows. Используйте функцию
GetWindowsDirectory
, чтобы получить путь к этому каталогу.
- Текущий каталог.
- Каталоги, перечисленные в переменной окружения
PATH
. Обратите внимание, что это не включает путь для каждого приложения, указанный в разделе реестра приложений. Ключ App Paths не используется при вычислении пути поиска DLL.
Так что, если вы не именовании DLL то же самое, как системный DLL (который вы, очевидно, не следует делать, никогда, ни при каких обстоятельствах), порядок поиска по умолчанию будет начать поиск в каталоге из которого была загружена ваша заявка. Если вы разместите DLL там во время установки, он будет найден. Все сложные проблемы уходят, если вы просто используете относительные пути.
Просто написать:
[DllImport("MyAppDll.dll")] // relative path; just give the DLL's name
static extern bool MyGreatFunction(int myFirstParam, int mySecondParam);
Но если не работу по какой-либо причине, и вам необходимо, чтобы заставить приложение искать в другом каталоге для DLL, вы можете изменить поиск по умолчанию с использованием SetDllDirectory
function.
Обратите внимание, что, согласно документации:
После вызова SetDllDirectory
, стандартный поиск DLL путь:
- каталог, из которого загружается приложение.
- Адрес, заданный параметром
lpPathName
.
- Системный каталог. Используйте функцию
GetSystemDirectory
, чтобы получить путь к этому каталогу.
- 16-разрядный системный каталог. Нет функции, которая получает путь к этому каталогу, но выполняется поиск.
- Каталог Windows. Используйте функцию
GetWindowsDirectory
, чтобы получить путь к этому каталогу.
- Каталоги, перечисленные в переменной окружения
PATH
.
Так до тех пор, как вы называете эту функцию перед вызовом функции импортируемой из DLL в первый раз, вы можете изменить путь поиска, используемый по умолчанию для поиска библиотек DLL. Выгода, конечно, состоит в том, что вы можете передать значение динамическое значение этой функции, которая вычисляется во время выполнения. Это невозможно с атрибутом DllImport
, поэтому вы по-прежнему будете использовать относительный путь (только имя DLL) и полагаться на новый порядок поиска, чтобы найти его для вас.
Вам нужно будет P/вызвать эту функцию. Декларация выглядит так:
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
Просто разверните DLL в той же папке, что и EXE, поэтому вам не нужно ничего делать, кроме указания имени DLL без пути. Другие схемы возможны, но все это хлопотно. –
Дело в том, что это будет MS Office Excel Add In, поэтому я не считаю, что dll в каталоге exe будет лучшим решением ... – Jsncrdnl
Ваше решение неверное. Не размещайте файлы в Windows или системных папках. Они выбрали эти имена по какой-то причине: они предназначены для системных файлов Windows. Вы не создаете один из них, потому что вы не работаете в Microsoft в команде Windows. Помните, что вы узнали в детском саду о том, как использовать вещи, которые не принадлежат вам без разрешения, и помещать ваши файлы где угодно, но там. –