我有两个版本的System.Data.SQLite.DLL - 分别是x86和x64平台。其中x86版本保存在应用程序文件夹中,而x64版本保存在appFolder\x64文件夹中。 应用程序编译为AnyCPU。 如何根据Windows平台加载所需的SQLite版本?
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);
一些杀毒程序会阻止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,而不是在磁盘上搜索它。如果开发和客户机器可能具有不同的处理器架构,则可能需要多个二进制包。 对于这种情况,使用本地库预加载功能是非常推荐的。它自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程序集
您可以使用Environment.Is64BitProcess来识别进程是否为64位。 (尽可能避免在流程控制中捕获异常。)
你可不可以在你的解决方案中使用SQLite的源代码作为一个单独的项目,而不是预编译的程序集?使用AnyCPU,系统本身会处理所有事情,你不需要在代码中做任何操作...