gpt4 book ai didi

c# - SQLite 的 DLL hell

转载 作者:IT王子 更新时间:2023-10-29 04:31:21 26 4
gpt4 key购买 nike

我们的一些用户遇到了运行时加载的 sqlite.interop.dll 版本问题,这真是令人头疼。

背景:为 AnyCPU 构建的 WPF 应用程序,使用 SQlite .NET 和 sqlite.interop.dll 版本 1.0.89 部署。我们同时部署 x86 和 x64 dll,并使用 SQLite 中包含的延迟加载。这一直很好,直到最近,当我们开始从最近购买新戴尔机器的用户那里收到一些支持问题时。似乎有一个旧版本的 sqlite.interop.dll (v.1.0.80),不知何故,它比我们发布的版本优先加载。我们得到的错误是缺少入口点“sqlite3_changes_interop”。

我们尝试过的:

  1. 更改设置以在安装期间将适当的 dll (x86/64) 复制到与可执行文件相同的目录(即没有单独的 x86/x64 文件夹)。这意味着我们不再使用延迟加载,因为正确的 dll 在可执行目录中可用(尽管我们没有在 sqlite.net 中明确禁用延迟加载机制)。这不能解决问题..

  2. 在应用程序首次加载时显式加载 sqlite.interop.dll。同样,这似乎无法解决问题。

最近几年dll加载位置的顺序似乎有些变化,我可能不太了解。我一直认为可执行目录中的 dll 将获得第一优先权,并且已显式加载的 dll 会阻止在应用程序生命周期内重新加载相同的 dll,所以在我的一生中,我无法理解这里发生了什么.

任何人都可以阐明这里可能发生的事情吗?由于我根本无法在本地重现问题 - 例如通过在我的系统路径中放置错误版本的 dll 等。这让我觉得 GAC 可能会发挥作用?

真的坚持这一点,所以任何帮助都会很棒。

此外 - 作为最后的手段 - 我可能会考虑恢复到相同的 1.0.80 版本,这样我们就不会遇到这个问题。有谁知道我们可以从哪里获取旧版本的 sqlite.net 和 sqlite.interop.dll?

编辑 - 一些附加信息:

冲突是由与 Dell Backup and Recovery 一起安装的 sqlite.interop.dll 版本 1.0.80 的副本引起的。它安装在所有新的 Dell 机器上,并且在此类机器上安装我们的软件的用户都会遇到此问题。此戴尔软件还使用 System.Data.SQLite.dll。

sqlite.interop.dll 的正确版本与我们的可执行文件位于同一目录中,我对 dll 加载的所有了解都表明应该优先加载它。

虽然我们还不能在本地重现该问题,但看起来 interop.dll 的错误版本在路径上。此外,戴尔备份实用程序会在启动时自动运行。有谁知道这可能挂接到 dll 加载请求并提供错误文件的任何可能机制?

目前的思路是我们可以构建自己的 System.Data.SQLite.dll 并将互操作加载代码更改为特定命名的版本(例如 sqlite.interop.1.0.89.dll)。这不是一个很好的解决方案,但是..

最佳答案

我们的应用程序有同样的问题。正如您所提到的,问题在于 Dell Backup and Recovery 安装了一个 shell 扩展,该扩展使用了多个流行 dll 的旧版本。他们对任何启动文件对话框并使用这些库的应用程序都玩得很烂,因为 shell 扩展将它们的 dll 加载到您的 AppDomain 中。到目前为止,我们唯一的解决方案是告诉用户卸载 Dell Backup and Recovery。

如果你force your app to load the correct library正如dymanoid提到的,那么当它显示文件对话框时你的应用程序会崩溃(因为shell扩展会崩溃)。如果您不这样做,那么您的应用会在尝试从其数据库中读取时崩溃。

有趣的是,Dell Backup and Recovery 是屡犯者;它还breaks QT5以同样的方式。 recommended solution来自 QT 人员的是使用 -qtnamespace [name] 选项以不同的名称编译您的 QT 库。我们也许可以使用 system.data.sqlite 来装配类似的东西,但是我们必须编译我们自己的版本。

微软是aware of the problem ,但拒绝修复它。

我希望 Dell 的人已经实现了他们的 shell 扩展 like this .

Portroit Pro , SONAR , 和 AutoDesk解决这个问题的方法也是卸载Dell Backup and Recovery。

问题的典型堆栈跟踪在我们的应用程序中如下所示:

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. 
at System.Data.SQLite.UnsafeNativeMethods.sqlite3_open_interop(Byte[] utf8Filename, Int32 flags, IntPtr& db)
at System.Data.SQLite.SQLite3.Open(String strFilename, SQLiteConnectionFlags connectionFlags, SQLiteOpenFlagsEnum openFlags, Int32 maxPoolSize, Boolean usePool)
at System.Data.SQLite.SQLiteConnection.Open()
at STCommonShellIntegration.DataShellManagement.CreateNewConnection(SQLiteConnection& newConnection)
at STCommonShellIntegration.DataShellManagement.InitConfiguration(Dictionary`2 targetSettings)
at DBROverlayIcon.DBRBackupOverlayIcon.initComponent()

所以在回答 Track 的评论时,如果你想检测这个特定问题并给用户一些特别通知,你可以这样做:

AppDomain.CurrentDomain.UnhandledException += UEHandler;
//...
[HandleProcessCorruptedStateExceptions] //access violation
static void UEHandler(object sender, UnhandledExceptionEventArgs e){
var ex = e.ExceptionObject as Exception;
if( ex.ToString().Contains( "DBROverlayIcon" ){
//show some dialog here telling users to uninstall DBaR
}
}

关于c# - SQLite 的 DLL hell ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30833889/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com