Загрузка сборки x86 или x64

У меня есть две версии System.Data.SQLite.DLL - для платформы x86 и x64. Версия x86 хранится в папке приложения, а версия x64 хранится в папке appFolder\x64. Приложение составлено как AnyCPU. Как я могу загрузить нужную версию SQLite в соответствии с платформой Windows?

Ответ 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-битной платформе).
  • используйте привязку сборки в конфигурации вашего веб-приложения (возможно, в конфигурации устройства).
  • Полностью квалифицируйте любые частичные ссылки на сборку в конфигурации вашего веб-приложения.