P / Invoke динамический путь поиска DLL - PullRequest
13 голосов
/ 09 марта 2010

У меня есть приложение, которое P / вызывает библиотеку DLL, находящуюся в том же каталоге, что и само приложение.

Теперь (из-за того, что Canon производит один из самых клевых API), мне нужно поддержать две версии этого API и определить во время выполнения, какую из них использовать (старую или новую). Поскольку библиотеки DLL имеют одинаковые имена (первая загружает другие библиотеки DLL с одинаковыми именами, поэтому переименование первых не поможет), я должен хранить их в разных каталогах.

Отсюда мой вопрос: какие опции у меня есть, чтобы контролировать, какой каталог использует DLL, указанная в объявлении DllImport?

Полагаю, я могу начать, попробовав любую из этих двух идей:

1) Используйте «SetDllDirectory», чтобы установить желаемый каталог перед выполнением первого P / Invoke, а затем сбросьте его.

2) Загрузите нужную DLL вручную, используя «LoadLibraryEx», и надеемся, что это поможет.

Но есть ли еще ".NET: простой способ" попробовать в первую очередь?

ОБНОВЛЕНИЕ: Я понимаю, что могу собрать весь доступ к DLL в двух отдельных сборках .Net, а затем поместить каждую из них в отдельный каталог с соответствующими файлами API. Затем я могу динамически загружать правильную сборку .Net и автоматически загружать правильную DLL. Любая причина, которая не должна работать?

Я могу подумать об одном: как мне отладить этот материал? Можно сказать Visual Studio, что сборка (содержащаяся в моем решении) должна быть помещена в подкаталог и отлажена оттуда?

Ответы [ 3 ]

10 голосов
/ 09 марта 2010

Мои соболезнования, я видел один из API, и он действительно был ужасно плохим. Большая проблема в том, что вам нужно будет убедить Windows найти DLL. Они не будут в вашем каталоге .exe, поэтому по умолчанию не будет работать. Использование SetDllDirectory () будет работать, также как и Environment.CurrentDirectory. LoadLibrary не может работать, маршаллер P / Invoke будет использовать сам LoadLibrary.

Если это вообще вариант, вы можете использовать разные имена для двух объявлений P / Invoke, используя разные аргументы для конструктора DllImport () и используя атрибут EntryPoint. Не похоже, что это полетит.

2 голосов
/ 09 марта 2010

Я думаю, что второй вариант будет работать, но он потребует написания большого количества кода для управления загрузкой DLL в .net.

Сначала можно работать, но мне это тоже не нравится.

Вот мое предложение: вы можете указать полный путь (и может быть относительным) в DllImport [DllImport(@"C:\dll\a32.dll"]

1 голос
/ 09 марта 2010

Ваш первый вариант (P / Invoke с SetDllDirectory) - это вариант, который я лично предпочитаю. К сожалению, не существует «.NETish» способа обработки загрузки собственных DLL-библиотек ... который имеет смысл.

...