Загрузка. net Оболочке не удается загрузить собственную зависимость - PullRequest
1 голос
/ 18 апреля 2020

Ситуация: несколько версий класса-оболочки. net, все с одинаковыми именами. Мы хотим динамически загрузить 1 из оболочек в методе сервиса wcf. Я планирую настроить папки с каждой оберткой + зависимой DLL. Мы будем использовать switch или if для каждого выбранного пользователем варианта версии.

У меня есть Assembly.LoadFrom с путем и я могу создать экземпляр класса-оболочки. Но вызов метода в оболочке завершается с ошибкой «не удается загрузить или найти CTV.dll».

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

Environment.SetEnvironmentVariable ("Путь", [путь к ctv.dll в папке], EnvironmentVariableTarget.Process);

Но это не имеет никакого эффекта, та же ошибка происходит.

Есть ли что-то, что мне не хватает. Кажется, был бы ответ на это.

Есть ли другой способ справиться с этим вариантом использования?

1 Ответ

1 голос
/ 18 апреля 2020

Решение 1:

На первый взгляд, загрузка собственной нативной библиотеки dll перед загрузкой управляемой оболочки кажется хорошим решением (при использовании вызова LoadLibrary с абсолютным путем)

[DllImport("kernel32", SetLastError=true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);

С docs.microsoft.com :

Если в строке указан полный путь, функция ищет только этот путь для модуля.

Я хочу поговорить и об альтернативе, которую я попытался с успехом.

Решение 2:

Мы можем добавить новый путь в порядок поиска LoadLibrary используя собственный API SetDllDirectory.

Собственные библиотеки загружаются с использованием функции LoadLibrary , и для загружаемых библиотек существует определенный порядок поиска каталогов .

См. Этот раздел, взятый из документации функции LoadLibrary:

Путь поиска можно изменить с помощью функции SetDllDirectory. Это решение рекомендуется вместо использования SetCurrentDirectory или жесткого кодирования полного пути к DLL.

Я добавил символический c вызов взаимодействия для несуществующего модуля:

[DllImport("oguzozgul.dll")]
static extern uint InvokeOguzOzgul(IntPtr oguz, uint ozgul);

Затем вызвал эту функцию и контролировал поведение поиска с помощью ProcMon

enter image description here

Вы можете ясно видеть, в каком порядке выглядит LoadLibrary для родного образа. (В моей системе)

И затем, перед любыми вызовами этого несуществующего модуля, я вызвал [SetDllDirectory]:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetDllDirectory(string lpPathName);

// Calling SetDllDirectory:
SetDllDirectory("c:\\temp\\");

И снова вызвал метод. Результат выглядит следующим образом.

Сразу после проверки папки процесса, LoadLibrary проверяет введенный путь.

Так что если вы вызываете SetDllDirectory и добавляете правильный путь к каталогу в порядок поиска LoadLibrary, требуемая версия собственной библиотеки DLL должна автоматически загружаться оттуда, когда этого требует управляемая оболочка.

Надеюсь, это поможет.

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...