针对x86/x64架构的SQLite动态链接库

14
我正在开发VB.net程序,并使用System.Data.SQLite .NET预编译二进制文件。然而,它不适用于x64体系结构,我遇到了 经典的文化问题和无法加载正确文件的问题。请注意,保留HTML标签,不涉及解释。
System.BadImageFormatException: 
Could not load file or assembly 'System.Data.SQLite, Version=1.0.65.0, Culture=neutral,
 PublicKeyToken=db937bc2d44ff139' or one of its dependencies. An attempt was made to load a program with an incorrect format.
File name: 'System.Data.SQLite,
 Version=1.0.65.0,
 Culture=neutral, 
 PublicKeyToken=db937bc2d44ff139'

您好,以下是您需要翻译的内容:

是否有一种方法只使用一个dll,例如:

  1. 添加一些类似#IFDEF(x86包含某些代码部分)或其他x64代码的指令。
  2. 将dll合并为一个。
  3. 在VB.net中引用此dll。

您认为还有其他更好的想法吗?我希望只进行一次编译,而不是为x32和x64分别进行编译。

例如(32位):

请注意保留原文中的HTML标签,且不要写出解释,谢谢!
Private Shared Sub OpenConection(ByRef Conn As SQLite.SQLiteConnection)
    Conn = New SQLite.SQLiteConnection("Data Source=" & System.Environment.CurrentDirectory & "\database.db")
    Conn.Open()
End Sub

Private Shared Sub CloseConection(ByRef Conn As SQLite.SQLiteConnection)
    Conn.Close()
    Conn.Dispose()
    Conn = Nothing
End Sub

Public Shared Function ReturnSelect(ByVal DataTAbleName As String, ByVal sQuery As String, ByVal sWhere As String) As Data.DataTable
    Dim lDT As New DataTable
    Dim lTA As New SQLite.SQLiteDataAdapter
    If DataTAbleName Is Nothing Then Return New DataTable(DataTAbleName)
    Try
        OpenConection(conexion)
        lTA = New SQLite.SQLiteDataAdapter("SELECT " & sQuery & " FROM  " & DataTAbleName & IIf(sWhere <> String.Empty, " WHERE ", "") & sWhere, conexion)
        lTA.Fill(lDT)
    Catch ex As Exception
        Throw ex
    Finally
        CloseConection(conexion)
        lTA.Dispose()
        lTA = Nothing
    End Try
    Return lDT
End Function

如何将它改为适用于64位架构?也许包括32位和64位dll,在函数中进行一些操作即可。
Try
    Instance = Me
    'Check If Homidom Run in 32 or 64 bits
    If IntPtr.Size = 8 Then _OsPlatForm = "64" Else _OsPlatForm = "32"
    'continue code

Catch ex As Exception
    ' ex.Message
End Try
5个回答

25

有多种选项可用于从.NET程序集中使用SQLite。第一步是升级到比古老的1.0.65版本更新的版本。可以从这里下载最新版本:http://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki,或通过SQLite NuGet包下载。

如果需要在32位和64位下运行,一种选择是使用本地库预加载选项,其中你将本地二进制文件分别放在不同的目录中,使其看起来像这样:

  • \App.exe(可选的,仅受管理的应用程序可执行文件程序集)
  • \App.dll(可选的,仅受管理的应用程序库程序集)
  • \System.Data.SQLite.dll(必需的,仅受管理的核心程序集)
  • \System.Data.SQLite.Linq.dll(可选的,仅受管理的LINQ程序集)
  • \x86\SQLite.Interop.dll(必需的,x86本机Interop程序集)
  • \x64\SQLite.Interop.dll(必需的,x64本机Interop程序集)

另一个选择是构建两个版本的应用程序,在每个版本中引用适当的混合模式程序集。你将最终得到两个版本,但它们稍微简单一些,因为你不需要额外的子目录和本机*.Interop.dll文件。

在这些情况下,你不需要在32位和64位之间进行代码差异或可选编译。从不同的NuGet包安装可能是最容易入手的方法。

最后一个选择是使用名为C#-SQLite的仅管理克隆版:https://code.google.com/p/csharp-sqlite/。它是SQLite引擎移植到托管的C#,所以整个程序作为AnyCPU运行,位数不是问题。


注意,我必须在二进制压缩文件中找到Interop DLL,以便为我正在使用的.NET目标进行工作。 - Garry Polley

6

我几年前也遇到了同样的问题,对我来说最好的解决方案是:

  • 下载最新版本的库
  • 在 bin 路径中只放置 System.Data.SQLite.dll 和可能的 System.Data.SQLite.Linq.dll
  • 将 x86 的 SQLite.Interop.dll 库放入 c:\Windows\SysWOW64
  • 将 x64 的 SQLite.Interop.dll 库放入 c:\Windows\System32
  • 将项目编译为 Any CPU,只引用 System.Data.SQLite(即 bin 路径中的 dll)
  • 享受吧!

这样,.NET Framework 在运行时会自动加载正确(x86 vs x64)的库,而无需在 GAC 或类似位置注册任何内容。

希望这可以帮到您。


1
我应该将哪个 System.Data.SQLite.dll 添加到 bin 文件夹中,x32 还是 x64 可用的 dll?我已经下载了 x32 和 x64 两个版本,每个版本都有 System.Data.SQLite.dll,它们的大小不同... - edgarmtze
嗯,它们应该具有相同的大小,你下载了哪些版本? - Tobia Zambon
我下载了.NET 2的二进制文件,因为我的应用程序无法使用> .NET 2。 我做错了什么吗? - edgarmtze
2
它是正确的,这两个库是相同的,我已经用文件比较器检查过了。你需要下载x86版本x64版本 - Tobia Zambon
10
为什么这个回答会被接受?把库扔进系统文件夹里,真的吗?这会让部署变成噩梦。 - Odys
1
我赞同@Odys所说的--这不是正确的做法。将库文件放入全局程序集缓存中可以解决问题,但只能在您自己的计算机上运行。对于其他安装了该程序的人来说,您的程序仍然无法正常工作。 - Eric Dand

1

使用Nuget可以轻松解决问题的现状。 安装后,搜索SQLite即可:

PM> Install-Package System.Data.SQLite 

我使用全新的电脑和VS完成了这个操作,我需要SQLite并且已经完成了安装,一切都运行良好。


这仍然会给您两个DLL文件。OP想知道如何只使用其中一个。 - ProfK

1
没有这个东西。因为这些*.dll只是本地c/c++*.dll的包装器。32位的.NET应用程序必须使用32位的c/c++ dll,而64位的.NET应用程序必须使用64位的c/c++ dll。我很久没有使用vb.net了,不确定您是否可以像在c#中那样配置目标平台。如果可以,您应该这样做并选择正确的interop dll。您还应该决定是否需要32位或64位。

那我需要编译两次,一次为32位,另一次为64位吗? - edgarmtze
是的,如果你想提供32位和64位版本的话。因为如果你将目标设置为“任何CPU”,它将编译为目标版本(64位或32位取决于目标Windows)。你必须将目标设置为x86(32位)或x64(64位)。 - user743414

1
这里@Govert和@TobiaZambon提供的答案是正确的方法。但是,对于其他读者,另一个选择是使用x86版本的System.Data.Sqlite dll,并仅为x86平台编译您的应用程序。即不要编译为AnyCPU,这意味着当它在x64机器上运行时,Windows将以32位模式运行它,并且能够加载32位dll。
这是否有用取决于您的情况,但如果您正在构建部署到工作站的应用程序,则这是一个相当简单的解决方案。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接