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

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

13 голосов
/ 24 сентября 2010

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

Ответы [ 7 ]

17 голосов
/ 19 мая 2011

Если вы используете 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);
11 голосов
/ 14 января 2013

Некоторые антивирусы предотвращают 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 будет использовать DLL-библиотеку в памяти вместо поиска на диске.

5 голосов
/ 24 октября 2012

Существует встроенная поддержка для этого в 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

3 голосов
/ 24 сентября 2010

Я удивлен, что это работает вообще.Сначала он должен найти версию x86 и потерпеть неудачу.Неудачное связывание сборки не приводит к другой попытке через AssemblyResolve.

Очевидно, что CLR на самом деле не может найти версию x86, иначе это может привести к ошибке в режиме x64.Другими словами, когда вы исправите проблему, вы сломаете 64-битный код.Сначала найдите проблему x86, используйте Fuslogvw.exe, чтобы увидеть, какие папки проверяются на сборку.

Реальное исправление должно включать в себя перемещение сборки x86 в отдельную папку и соответствующую настройку обработчика событий.Вы можете протестировать IntPtr.Size, чтобы узнать, работаете ли вы в 64-битном режиме (размер == 8).Также обязательно сгенерируйте полное имя пути, использование относительного пути, как вы делаете сейчас, может привести к сбою, когда рабочий каталог приложения не установлен там, где вы надеетесь.Assembly.GetEntryAssembly (). Местоположение указывает путь к EXE-файлу.

1 голос
/ 24 сентября 2010

Вы можете использовать Environment.Is64BitProcess , чтобы идентифицировать процесс как 64-битный. (Я бы старался избегать перехвата исключений в качестве контроля потока, где это возможно.)

0 голосов
/ 28 октября 2011
  1. установить соответствующую DLL в GAC (например, 64-битную версию на 64-битной платформе)
  2. использовать привязку сборки в конфигурации вашего веб / приложения (возможно, в конфигурации машины)
  3. Полностью квалифицируйте любые ссылки на частичные сборки в конфигурации вашего веб / приложения.
0 голосов
/ 24 сентября 2010

Не могли бы вы просто использовать источник SQLite в качестве отдельного проекта в своем решении вместо предварительно скомпилированной сборки? Используя AnyCPU, система сама позаботится обо всем, и вам не нужно делать это в коде ...

...