Некоторые клиенты не могут загрузить SQLite.Interop.dll

Есть приложение, которое использует SQLite. Ссылка на System.Data.SQLite и SQLite.Interop.dll (для платформ х64 и х86) добавлены статично, версия 1.0.112.0. (у всех 3 файлов) (В тестовый проект SQLite была добавлена через NuGet, а оттуда скопирована в текущий проект). Файлы System.Data.SQLite и SQLite.Interop.dll (в папках х86 и х64) присутствуют на клиентской машине. Версия .Net 4.7.2.

Большинство клиентов работают нормально, но несколько выбрасывают исключение с текстом "Unable to load DLL 'SQLite.Interop.dll'". На своей машине собирал версии под х86 и х64, в каждом случае грузилась SQLite.Interop.dll из соответствующей папки (Если по соответсвующему пути не лежала SQLite.Interop.dll, то было исключение).

В сторону чего смотреть, чтобы избежать такого исключения на всех машинах клиентов?

Есть догадка, что у клиента отсутствует Microsoft Visual C++ Redistributable. Я могу каким-то образом поместить локальную копию этого компонента в свое приложение? - Версия не верна, на машине уже установлен Microsoft Visual C++ Redistributable.

Следующее предположение - система может найти SQLite.Interop.dll, но во время загрузки или инициализации случается ошибка, которая оберткой (System.Data.SQLite) трактуется как DllNotFoundException.


Ответы (1 шт):

Автор решения: Виталий Ефимов

После длительного поиска была найдена причина появления DllNotFoundException. Это связано с тем, что SQLite.Interop.dll имеет зависимость от msvcr120. (Для выяснения этого использовался Dependency Walker). Но тут есть один нюанс, если приложение для платформы х64, то этот файл ожидается найти в папке C:\Windows\System32. Но если платформа х86, то файл должен быть по пути C:\Windows\SysWOW64. Я увидел что msvcr120 есть в папке System32 и решил что раз либа есть, то проблема в другом.

Самое простое решение - собирать приложение под платформу х86, а рядом с exe-файлом размещать соответствующий msvcr120.

Нашел более оптимальное решение проблемы. Соответствующая версия msvcr120 размещается рядом с SQLite.Interop.dll в папке х86 или х64. Перед использованием sqlite (например в кострукторе Application или в его перегруженном методе OnStartup()) нужно добавить нашу папку в переменную окружения PATH.

var pathVar = Environment.GetEnvironmentVariable("PATH");
       
string customDllFolder;
if (Environment.Is64BitProcess)
{
    customDllFolder = Path.Combine(Environment.CurrentDirectory, "x64");
}
else
{
    customDllFolder = Path.Combine(Environment.CurrentDirectory, "x86");
}

pathVar = string.Concat(pathVar, ";", customDllFolder);
Environment.SetEnvironmentVariable("PATH", pathVar, EnvironmentVariableTarget.Process);

Это решение лучше, так как мы будем использовать локальную копию msvcr120 только в том случае, если ее нет на машине пользователя. А также мы можем собирать приложение для обеих платформ (х86 и х64). Этот подход может быть использован и для других неуправляемых библиотек.

→ Ссылка