ASP.NET Core 6启动server.dll时找不到dblgen17.dll的问题
问题:SQL Anywhere非托管DLL加载异常(仅
dotnet server.dll启动时触发) 问题场景
已将SQL Anywhere所需的64位非托管DLL添加到项目目录,构建时这些文件会复制到bin文件夹根目录。调试或dotnet run启动项目时运行正常,但通过dotnet server.dll直接启动ASP.NET Core 6构建后的程序集时,抛出以下异常:
System.Exception: The type initializer for 'Sap.Data.SQLAnywhere.SAConnection' threw an exception. ---> System.TypeInitializationException: The type initializer for 'Sap.Data.SQLAnywhere.SAConnection' threw an exception. ---> Sap.Data.SQLAnywhere.SAException (0x80004005): Cannot find the language resource file (dblgen17.dll). at Sap.Data.SQLAnywhere.SAUnmanagedDll..ctor() at Sap.Data.SQLAnywhere.SAUnmanagedDll.get_Instance() at Sap.Data.SQLAnywhere.SAConnection..cctor() --- End of inner exception stack trace --- at Sap.Data.SQLAnywhere.SAConnection..ctor() ---> System.TypeInitializationException: The type initializer for 'Sap.Data.SQLAnywhere.SAConnection' threw an exception. ---> Sap.Data.SQLAnywhere.SAException (0x80004005): Cannot find the language resource file (dblgen17.dll). at Sap.Data.SQLAnywhere.SAUnmanagedDll..ctor() at Sap.Data.SQLAnywhere.SAUnmanagedDll.get_Instance() at Sap.Data.SQLAnywhere.SAConnection..cctor() --- End of inner exception stack trace --- at Sap.Data.SQLAnywhere.SAConnection..ctor()
项目csproj配置如下:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net6.0-windows</TargetFramework> <Nullable>enable</Nullable> <ImplicitUsings>enable</ImplicitUsings> <Platforms>x64</Platforms> </PropertyGroup> <ItemGroup> <ContentWithTargetPath Include="Artifacts\Libraries\dbcon17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>dbcon17.dll</TargetPath> </ContentWithTargetPath> <ContentWithTargetPath Include="Artifacts\Libraries\dbicu17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>dbicu17.dll</TargetPath> </ContentWithTargetPath> <ContentWithTargetPath Include="Artifacts\Libraries\dbicudt17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>dbicudt17.dll</TargetPath> </ContentWithTargetPath> <ContentWithTargetPath Include="Artifacts\Libraries\dblgde17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>dblgde17.dll</TargetPath> </ContentWithTargetPath> <ContentWithTargetPath Include="Artifacts\Libraries\dblgen17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>dblgen17.dll</TargetPath> </ContentWithTargetPath> <ContentWithTargetPath Include="Artifacts\Libraries\dbodbc17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>dbodbc17.dll</TargetPath> </ContentWithTargetPath> <ContentWithTargetPath Include="Artifacts\Libraries\dbrsa17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>dbrsa17.dll</TargetPath> </ContentWithTargetPath> <ContentWithTargetPath Include="Artifacts\Libraries\sapcrypto.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> <TargetPath>sapcrypto.dll</TargetPath> </ContentWithTargetPath> </ItemGroup> <ItemGroup> <PackageReference Include="Dapper" Version="2.0.78" /> <PackageReference Include="Dapper.Contrib" Version="2.0.78" /> <PackageReference Include="**.Interfaces" Version="1.0.0" /> <PackageReference Include="**.Libraries.Common" Version="1.0.0" /> <PackageReference Include="**.Libraries.Database" Version="1.0.0" /> <PackageReference Include="**.Libraries.Logging" Version="1.0.0" /> <PackageReference Include="**.Libraries.MQTTHandling" Version="1.0.0" /> <PackageReference Include="**.Libraries.Translation" Version="1.0.0" /> <PackageReference Include="**.Utilities" Version="1.0.0" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.8" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="6.2.3" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.22.0" /> </ItemGroup> <ItemGroup> <Reference Include="Sap.Data.SQLAnywhere.Core.v2.1"> <HintPath>Artifacts\Sap.Data.SQLAnywhere.Core.v2.1.dll</HintPath> </Reference> </ItemGroup> <ItemGroup> <Resource Include="Artifacts\Libraries\dbcon17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> <Resource Include="Artifacts\Libraries\dbicu17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> <Resource Include="Artifacts\Libraries\dbicudt17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> <Resource Include="Artifacts\Libraries\dblgde17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> <Resource Include="Artifacts\Libraries\dblgen17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> <Resource Include="Artifacts\Libraries\dbodbc17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> <Resource Include="Artifacts\Libraries\dbrsa17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> <Resource Include="Artifacts\Libraries\sapcrypto.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> </ItemGroup> <ItemGroup> <None Update="bms.xml"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> </Project>
原因分析
- 工作目录差异:
- 调试或
dotnet run启动时,IDE或命令行工具会自动将工作目录设为项目根目录,同时可能将bin目录加入进程的PATH环境变量,确保非托管DLL可被找到。 - 直接运行
dotnet server.dll时,若从非bin目录启动,当前工作目录与DLL所在路径不一致,且PATH未包含bin目录,导致非托管DLL加载失败。
- 调试或
- csproj配置冗余:
项目同时用ContentWithTargetPath和Resource节点复制同一批DLL,可能引发复制逻辑冲突(虽当前DLL已复制到bin目录,但冗余配置可能导致不可预期问题)。 - 非托管DLL加载机制限制:
.NET加载非托管DLL时,优先搜索系统目录、当前工作目录、PATH环境变量中的路径,而非直接搜索程序集所在目录。若程序集所在目录不在搜索路径内,即使DLL存在也无法加载。
解决办法
方法1:切换到bin目录启动程序
打开命令行,先导航到server.dll所在的bin目录(例如cd bin\Release\net6.0-windows),再执行:
dotnet server.dll
确保当前工作目录与DLL所在目录一致,让系统直接找到非托管DLL。
方法2:临时添加bin目录到PATH环境变量
启动前执行以下命令(替换为实际bin路径),将bin目录加入系统搜索路径:
set PATH=%PATH%;C:\YourProject\bin\Release\net6.0-windows
再运行dotnet server.dll,确保非托管DLL可被系统找到。
方法3:优化csproj配置,移除冗余节点
删除csproj中的Resource节点组,仅保留ContentWithTargetPath节点,避免复制逻辑冲突:
<!-- 删除以下冗余节点组 --> <!-- <ItemGroup> <Resource Include="Artifacts\Libraries\dbcon17.dll"> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </Resource> ... 其他Resource节点 </ItemGroup> -->
方法4:代码中指定DLL搜索路径
在程序启动时,通过Windows API设置非托管DLL的搜索路径为程序集所在目录,确保加载逻辑不受工作目录影响:
using System; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Hosting; namespace YourNamespace { public class Program { [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool SetDllDirectory(string lpPathName); public static void Main(string[] args) { // 获取当前程序集所在目录 var assemblyDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); // 设置DLL搜索路径 SetDllDirectory(assemblyDir); CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); }); } }
方法5:验证运行时平台匹配
执行以下命令确认当前使用的.NET Runtime架构为x64,与SQL Anywhere DLL的平台一致:
dotnet --info
若显示为x86,需切换到x64版本的.NET Runtime重新运行。
内容的提问来源于stack exchange,提问作者Gregor Biswanger
相关产品推荐
相关产品推荐

