P/Invoke динамический путь поиска DLL

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

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

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

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

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

2) Загрузите желаемый DLL вручную с помощью "LoadLibraryEx" и надейтесь, что это добьется цели.

Но есть ли еще ".NET:ish путь" для испытания сначала?

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

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

13
задан Dan Byström 9 March 2010 в 20:12
поделиться

3 ответа

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

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

10
ответ дан 2 December 2019 в 00:45
поделиться

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

1
ответ дан 2 December 2019 в 00:45
поделиться

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

Первый вариант тоже может работать, но мне он не нравится.

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

2
ответ дан 2 December 2019 в 00:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: