У меня есть существующее приложение который 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, что блок (содержавшийся в моем решении) должен быть помещен в подкаталог и отлажен оттуда?
Мои соболезнования, я видел один из API, и он действительно был шокирующе плох. Более серьезная проблема заключается в том, что вам нужно будет убедить Windows найти DLL. Они не будут находиться в вашем каталоге .exe, поэтому по умолчанию они не будут работать. Использование SetDllDirectory() будет работать, использование Environment.CurrentDirectory тоже. LoadLibrary не может работать, маршаллер P/Invoke будет использовать LoadLibrary сам по себе.
Если это вообще возможно, вы можете использовать разные имена для двух объявлений P/Invoke, использовать разные аргументы для конструктора DllImport() и использовать атрибут EntryPoint. Не похоже, что это сработает.
Ваш первый вариант (P / Invoke с SetDllDirectory) - это вариант, который я лично предпочитаю. К сожалению, нет ".NETish" способа обрабатывать загрузку собственных DLL ... что имеет смысл.
Я думаю, что второй вариант будет работать, но это потребует написания большого количества кода для управления загрузкой dll в .net.
Первый вариант тоже может работать, но мне он не нравится.
Вот мое предложение: вы можете указать полный путь (и может быть относительный) в DllImport [DllImport(@"C:\dll\a32.dll"]