У меня есть две версии System.Data.SQLite.DLL - для платформы x86 и x64. Версия x86 хранится в папке приложения, а версия x64 хранится в папке appFolder\x64. Приложение составлено как AnyCPU. Как я могу загрузить нужную версию SQLite в соответствии с платформой Windows?
Загрузка сборки x86 или x64
Ответ 1
Если вы используете SQLite из http://system.data.sqlite.org, то System.Data.SQLite.DLL полностью управляется. Существует базовая встроенная DLL, SQLite.Interop.DLL, которая должна изменяться в зависимости от процесса (32- или 64-разрядная).
Я развертываю собственные библиотеки в папке ".\Native\X64" для 64-разрядных и ".\Native\X86" для 32-разрядных. Во время выполнения P/Invoke SetDllDirectory установите каталог загрузки DLL, указав правильный путь для процесса. http://msdn.microsoft.com/en-us/library/ms686203(v=vs.85).aspx
(Обратите внимание, что я не знаком с архитектурой устаревшей версии System.Data.SQLite.DLL от http://sqlite.phxsoftware.com)
private static class NativeMethods
{
[DllImport("kernel32.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern bool SetDllDirectory(string pathName);
}
...
// Underlying SQLite libraries are native.
// Manually set the DLL load path depending on the process.
var path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Native");
if(IntPtr.Size == 8) // or: if(Environment.Is64BitProcess) // .NET 4.0
{
path = Path.Combine(path, "X64");
}
else
{
// X32
path = Path.Combine(path, "X86");
}
NativeMethods.SetDllDirectory(path);
Ответ 2
Некоторые антивирусные программы, препятствующие SetDllDirectory(), заняли у меня много времени, чтобы понять это. Мы используем
System.Reflection.Assembly myass = System.Reflection.Assembly.GetExecutingAssembly();
FileInfo fi = new FileInfo(myass.Location);
System.IntPtr moduleHandle = LoadLibraryEx(fi.Directory.FullName + "\\x64\\SQLite.Interop.DLL", IntPtr.Zero, 0);
для загрузки x64 DLL с явным путем. Он загружается в этот момент, и .NET Runtime будет использовать DLL в памяти вместо поиска на нем диска.
Ответ 3
В версии 1.0.80.0 и более поздней версии имеется встроенная поддержка.
Если машины разработки и клиента могут иметь разные архитектуры процессоров, может потребоваться несколько двоичных пакетов. Для этой ситуации настоятельно рекомендуется использовать функцию предварительной загрузки встроенной библиотеки. Он доступен с версии 1.0.80.0 и включен по умолчанию. (со страницы загрузки)
Однако, чтобы заставить его работать в моем собственном подключаемом модуле, мне также пришлось добавить это, прежде чем ссылаться на SQLite в первый раз:
// Make SQLite work... (loading dll from e.g. x64/SQLite.Interop.dll)
System.Environment.SetEnvironmentVariable("PreLoadSQLite_BaseDirectory", System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location));
Sql.Data.SQLite...
Смотрите этот вопрос: Новые смешанные сборки SQLite
Ответ 4
Я удивлен, что это работает вообще. Сначала он должен найти версию x86 и выйти из строя. Сбой сбоя сборки не создает другой попытки с помощью AssemblyResolve.
Очевидно, что CLR на самом деле не может найти версию x86, иначе это также будет работать в режиме x64. Другими словами, когда вы исправляете проблему, вы разрываете 64-битный код. Сначала попробуйте проблему x86, используйте Fuslogvw.exe, чтобы узнать, какие папки исследуются для сборки.
Реальное исправление должно включать перемещение сборки x86 в отдельную папку, а также соответствующую настройку обработчика событий. Вы можете протестировать IntPtr.Size, чтобы узнать, работаете ли вы в 64-битном режиме (Size == 8). Также обязательно создайте полное имя пути, используя относительный путь, как сейчас, может привести к сбою, когда рабочий каталог приложения не установлен там, где вы надеетесь. Assembly.GetEntryAssembly(). Место получает путь к EXE.
Ответ 5
Вы можете использовать Environment.Is64BitProcess, чтобы идентифицировать процесс как 64 бит. (Я бы постарался избежать исключения исключений в качестве контроля потока, где это возможно.)
Ответ 6
Не могли бы вы просто использовать источник SQLite в качестве отдельного проекта в своем решении вместо предварительно скомпилированной сборки? Используя AnyCPU, система сама позаботится обо всем, и вам не нужно делать это в коде...
Ответ 7
- установить соответствующую DLL в GAC (например, 64-битную версию на 64-битной платформе).
- используйте привязку сборки в конфигурации вашего веб-приложения (возможно, в конфигурации устройства).
- Полностью квалифицируйте любые частичные ссылки на сборку в конфигурации вашего веб-приложения.