P/Вызов динамического пути поиска DLL

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

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

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

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

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

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

Но есть ли еще ".NET: ish way", чтобы попробовать сначала?

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

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

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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