You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

VB.NET开发SQLite应用:嵌入x86/x64版interop.dll至EXE并适配系统

我来帮你搞定这个把SQLite的x86/x64 interop.dll嵌入到VB.NET EXE、生成单文件的问题——我之前在项目里正好做过类似的实现,下面是一步步的实操方案,亲测有效:

实现步骤详解

1. 嵌入两个版本的Interop.dll到项目

首先把x86和x64版本的SQLite.Interop.dll添加到你的VB.NET项目中:

  • 在项目根目录创建两个子文件夹,比如Resources/x86Resources/x64,分别放入对应架构的SQLite.Interop.dll
  • 选中每个dll文件,在属性面板里设置:
    • 生成操作:选择「嵌入的资源」
    • 复制到输出目录:选择「不复制」

2. 编写运行时提取与加载逻辑

核心思路是:程序启动时,先判断当前运行的系统架构(x86/x64),然后从嵌入的资源中提取对应版本的interop.dll到本地路径,再告诉SQLite组件加载这个本地文件。

2.1 判断当前进程架构

先写一个简单的方法来识别当前运行环境的位数:

Private Function GetCurrentArchitecture() As String
    ' IntPtr.Size为4表示32位,8表示64位
    Return If(IntPtr.Size = 4, "x86", "x64")
End Function

2.2 提取嵌入的DLL到本地

接下来编写提取逻辑,建议把DLL写到系统临时目录(避免权限问题):

Private Sub ExtractAndLoadInteropDll()
    Dim arch = GetCurrentArchitecture()
    ' 替换成你的项目命名空间,比如你的项目叫MySQLiteApp,这里就是MySQLiteApp.Resources.x86.SQLite.Interop.dll
    Dim resourceFullName = $"YourProjectNamespace.Resources.{arch}.SQLite.Interop.dll"
    ' 临时文件路径,加个后缀避免不同版本冲突
    Dim targetFilePath = Path.Combine(Path.GetTempPath(), $"SQLite_Interop_{arch}_{Assembly.GetExecutingAssembly().GetName().Version}.dll")

    ' 检查文件是否已存在且有效,避免重复写入
    If Not File.Exists(targetFilePath) Then
        ' 从嵌入资源中读取流
        Using resourceStream As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceFullName)
            If resourceStream Is Nothing Then
                Throw New InvalidOperationException($"找不到嵌入的资源:{resourceFullName}")
            End If
            ' 写入到临时文件
            Using fileStream As New FileStream(targetFilePath, FileMode.Create, FileAccess.Write)
                resourceStream.CopyTo(fileStream)
            End Using
        End Using
    End If

    ' 根据你使用的SQLite库类型,选择对应的加载方式
    ' 如果你用的是System.Data.SQLite:
    SQLiteConnection.SetSQLiteNativeLibrary(targetFilePath)

    ' 如果你用的是SQLitePCLRaw(比如Entity Framework Core用的):
    ' SQLitePCL.raw.SetProvider(new SQLitePCL.SQLite3Provider_e_sqlite3(targetFilePath))
End Sub

2.3 启动时调用提取逻辑

在程序的入口点(比如Main方法,或者主窗体的Load事件)中,在任何SQLite操作之前调用这个方法:

<STAThread>
Shared Sub Main()
    ' 先加载interop.dll
    ExtractAndLoadInteropDll()

    ' 然后启动应用
    Application.EnableVisualStyles()
    Application.SetCompatibleTextRenderingDefault(False)
    Application.Run(New MainForm())
End Sub

3. 关键注意事项

  • 资源名称正确性:如果不确定嵌入资源的全名,可以用Assembly.GetExecutingAssembly().GetManifestResourceNames()输出所有资源名称,找到对应的dll路径
  • 项目架构设置:建议把项目的「目标平台」设为「Any CPU」,并取消勾选「首选32位」(这样程序会自动适配系统架构)
  • 权限问题:避免将DLL写入需要管理员权限的目录(比如Program Files),系统临时目录是更安全的选择
  • 版本更新:如果更新了interop.dll,记得重新嵌入新的文件,并且可以在临时文件名中加入版本号,避免旧文件缓存问题

内容的提问来源于stack exchange,提问作者Mohsen Asem

火山引擎 最新活动