启用PublishSingleFile时SQLite连接抛空参数异常求助
将应用打包为单文件后,运行生成的exe时持续抛出如下异常:
Value cannot be null. (Parameter 'path1')
System.Private.CoreLib
at System.IO.Path.Combine(String path1, String path2)
at System.Data.SQLite.SQLiteConnection..ctor(String connectionString, Boolean parseViaFramework)
at System.Data.SQLite.SQLiteConnection..ctor(String connectionString)
at OrderManager.Program.Main() in C:\Users\Documents\GitHub\OrderManager\Program.cs:line 52
对应的代码片段:
51. File.AppendAllText(AppContext.BaseDirectory + @"\log.txt", ProgramParameters.connectionStringAdmin + Environment.NewLine); 52. connection = new(ProgramParameters.connectionStringAdmin);
已确认ProgramParameters.connectionStringAdmin内容正确:
Data Source = C:\Users\Documents\GitHub\OrderManager\bin\Release\net6.0-windows10.0.22621.0\publish\db\ManagerOrdini.db ; cache=shared; synchronous = NORMAL ; journal_mode=WAL; temp_store = memory; mmap_size = 30000000000;
Debug和Release模式下应用运行正常,无报错。已尝试在.csproj中设置排除System.Data.SQLite包的单文件嵌入,但无效:
<PropertyGroup> <ApplicationIcon>icon.ico</ApplicationIcon> <OutputType>WinExe</OutputType> <EmbedInteropTypes>True</EmbedInteropTypes> <_SuppressWinFormsTrimError>true</_SuppressWinFormsTrimError> <CustomResourceTypesSupport>true</CustomResourceTypesSupport> <BuiltInComInteropSupport>true</BuiltInComInteropSupport> <RuntimeIdentifier>win-x64</RuntimeIdentifier> <IsWebBootstrapper>false</IsWebBootstrapper> <CheckForOverflowUnderflow>true</CheckForOverflowUnderflow> <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> <DebuggerSupport>true</DebuggerSupport> <DebugType>embedded</DebugType> <PublishSingleFile>true</PublishSingleFile> </PropertyGroup> ... <ItemGroup> <PackageReference Include="System.Data.SQLite" Version="1.0.118"> <ExcludeFromSingleFile>true</ExcludeFromSingleFile> </PackageReference> ...
1. 手动指定SQLite原生库路径
单文件打包时,原生库会被提取到临时目录,旧版System.Data.SQLite可能无法自动识别。在初始化连接前添加以下代码:
// 获取单文件应用的实际运行目录 var runtimeDir = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName); // 强制指定SQLite原生库的查找目录 System.Data.SQLite.SQLiteConnection.SetConfig(System.Data.SQLite.SQLiteConfigOption.Directory, runtimeDir);
2. 升级System.Data.SQLite版本
你使用的1.0.118版本对.NET单文件发布的支持存在缺陷,升级到1.0.119及以上稳定版,新版本修复了大量单文件打包的兼容问题。
3. 优化csproj打包配置
在PropertyGroup中补充以下配置,确保原生库正确提取:
<PropertyGroup> <!-- 已有配置保留,新增以下项 --> <SelfContained>true</SelfContained> <PublishTrimmed>false</PublishTrimmed> <!-- 暂时关闭裁剪,避免SQLite组件被误删 --> </PropertyGroup>
同时直接排除SQLite原生库并强制复制到发布目录:
<ItemGroup> <NativeLibrary Include="sqlite3.dll"> <ExcludeFromSingleFile>true</ExcludeFromSingleFile> <CopyToPublishDirectory>Always</CopyToPublishDirectory> </NativeLibrary> </ItemGroup>
4. 改用相对路径构建连接字符串
绝对路径在单文件发布后可能失效,改用相对路径结合运行目录生成连接字符串:
var dbFullPath = Path.Combine(AppContext.BaseDirectory, "db", "ManagerOrdini.db"); ProgramParameters.connectionStringAdmin = $"Data Source={dbFullPath};cache=shared;synchronous=NORMAL;journal_mode=WAL;temp_store=memory;mmap_size=30000000000;";
5. 确保数据库文件被正确发布
检查数据库文件ManagerOrdini.db的属性,设置复制到输出目录为「始终复制」,并在csproj中添加:
<ItemGroup> <None Include="db\ManagerOrdini.db"> <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory> </None> </ItemGroup>
保证打包时数据库文件被复制到publish目录的db子文件夹中。
内容的提问来源于stack exchange,提问作者Razorphyn

