加载x86或x64程序集

时间:2010-09-24 13:16:06

标签: c# .net x86 64-bit

我有两个版本的System.Data.SQLite.DLL - 适用于x86和x64平台。 x86版本保留在应用程序文件夹中,x64版本保留在appFolder \ x64文件夹中。 该应用程序编译为AnyCPU。 如何根据Windows平台加载所需的SQLite版本?

7 个答案:

答案 0 :(得分:17)

如果您使用http://system.data.sqlite.org中的SQLite,则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

(请注意,我不熟悉来自http://sqlite.phxsoftware.com的遗留System.Data.SQLite.DLL版本的体系结构)

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);

答案 1 :(得分:11)

一些antivir progs阻止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,而不是在磁盘上搜索它。

答案 2 :(得分:5)

1.0.80.0及更高版本内置了对此的支持。

  

如果开发和客户机器可能具有不同的处理器体系结构,则可能需要多个二进制包。对于这种情况,强烈建议使用本机库预加载功能。它从版本1.0.80.0开始提供,默认情况下启用。 (from download page)

但是,为了让它在我自己的插件中工作,我还必须在第一次引用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...

请参阅此问题:New SQLite mixed assemblies

答案 3 :(得分:3)

我很惊讶这一点起作用了。它应该首先找到x86版本并失败。失败的程序集绑定不会通过AssemblyResolve产生另一次尝试。

显然,CLR实际上找不到x86版本,否则在x64模式下也会失败。换句话说,当您解决问题时,您将破坏64位代码。首先追逐x86问题,使用Fuslogvw.exe查看正在为程序集探测的文件夹。

真正的修复方法应该包括将x86程序集移动到单独的文件夹中并相应地调整事件处理程序。您可以测试IntPtr.Size以查明您是否以64位模式运行(大小== 8)。另外一定要生成一个完整的路径名,当应用程序的工作目录没有设置在你希望的位置时,使用像现在这样的相对路径会导致失败。 Assembly.GetEntryAssembly()。Location为您提供EXE的路径。

答案 4 :(得分:1)

您可以使用Environment.Is64BitProcess将进程标识为64位。 (我会尽量避免将异常作为流量控制来捕获。)

答案 5 :(得分:0)

难道您不能仅将SQLite源用作解决方案中的单独项目而不是预编译程序集吗?使用AnyCPU,系统本身将处理所有事情,您不必在代码中执行此操作...

答案 6 :(得分:0)

  1. 在GAC中安装适当的DLL(例如64位平台上的64位版本)
  2. 在您的web / app配置中使用程序集绑定(可能在机器配置中)
  3. 完全限定您的网络/应用配置中的任何部分程序集参考。