使用SQLite的DLL地狱 [英] DLL hell with SQLite

查看:94
本文介绍了使用SQLite的DLL地狱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们的某些用户在运行时加载的sqlite.interop.dll版本遇到了问题,这确实是个难题.

Some of our users are getting an issue with the version of sqlite.interop.dll that is being loaded at runtime, and it's a real head scratcher.

背景:为AnyCPU构建的WPF应用程序,已与SQlite .NET和sqlite.interop.dll版本1.0.89一起部署.我们同时部署x86和x64 dll,并使用SQLite附带的延迟加载.直到最近,这种情况一直很好,那时我们开始从最近(通常是最近)购买新Dell机器的用户那里获得一些支持问题.似乎有一个较旧的sqlite.interop.dll(v.1.0.80)版本,以某种方式正在优先于我们提供的版本进行加载.我们得到的错误是缺少入口点'sqlite3_changes_interop'.

Background: A WPF application built for AnyCPU, deployed with SQlite .NET and sqlite.interop.dll version 1.0.89. We deploy both x86 and x64 dlls and employ the delay loading included with SQLite. This has been fine until recently, when we started getting a few support issues from users that had - typically - recently purchased new Dell machines. It seems that there is an older version of sqlite.interop.dll (v.1.0.80) that, somehow, is getting loaded in preference to the one we ship. The error we get is a missing entry point, 'sqlite3_changes_interop'.

我们尝试过的事情:

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

  1. Changing the setup to simply copy the appropriate dll (x86/64) to the same directory as the executable during installtion (i.e. no separate x86/x64 folders). This means we no longer use the delay loading, as the correct dll is available in the executable directory (although we haven't explicitly disabled the delay loading mechanism in sqlite.net). This doesn't fix the problem..

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

Explicitly loading sqlite.interop.dll when the application first loads. Again, this does not seem to fix the issue.

近年来,dll加载位置的顺序似乎已经有所变化,我对此可能不太了解.我一直以为可执行文件目录中的dll将是第一个优先级,并且已经显式加载的dll会阻止在应用程序生命周期中重新加载该dll,所以我一生都无法理解这里发生的情况

It seems that the ordering of dll loading locations has been changing somewhat in recent years, and I may not have a good handle on it. I always assumed that a dll in the executable directory would get first preference, and that a dll that had been explicitly loaded would prevent the same dll being reloaded during the application lifetime, so for the life of my I cannot understand what is going on here.

任何人都可以阐明这里可能发生的事情吗?我根本无法在本地重现该问题,例如,通过将错误版本的dll放在我的系统路径等中.这使我认为也许GAC可能正在发挥作用?

Can anyone shed any light on what might be happening here? The problem is further compounded by the fact that I simply cannot reproduce the problem locally - e.g. by putting the wrong version of the dll in my system path etc. Which makes me think that maybe the GAC might be coming into play?

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

Really stuck on this one, so any help would be great.

-最后,我可能会考虑恢复到相同的1.0.80版本,这样我们就不会遇到这个问题.有谁知道我们可以在哪里找到较旧版本的sqlite.net和sqlite.interop.dll?

Also - as a final resort - I might consider reverting to the same 1.0.80 version, so that we don't get this issue. Does anyone know where we could source older versions of sqlite.net and sqlite.interop.dll?

编辑-一些其他信息:

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

The clash is caused by a copy of sqlite.interop.dll version 1.0.80 that is installed with Dell Backup and Recovery. This is installed on all new Dell machines, and users that install our software on such a machine all experience this issue. This Dell software also uses System.Data.SQLite.dll.

sqlite.interop.dll的正确版本与我们的可执行文件位于同一目录中,据我了解,有关dll加载的所有信息都建议应优先加载该文件.

The correct version of sqlite.interop.dll is located in the same directory as our executable, and everything I understand about dll loading suggests that this should be loaded in preference.

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

Although we have not yet been able to reproduce the issue locally, it appears that the bad version of interop.dll is not on the path. Furthermore, the Dell backup utility runs automatically on start-up. Does anyone know of any possible mechanism by which this might be hooking into dll load requests and serving the wrong file?

当前的思路是,我们可以构建自己的System.Data.SQLite.dll,并将interop加载代码更改为专门命名的版本(例如sqlite.interop.1.0.89.dll).未来不是一个很好的解决方案,但是..

The current line of thinking is that we might build our own System.Data.SQLite.dll and change the interop loading code to a specifically named version (e.g. sqlite.interop.1.0.89.dll). Not a nice solution going forwards, but..

推荐答案

我们的应用存在相同的问题.如您所述,问题是Dell Backup and Recovery安装了一个外壳扩展程序,该扩展程序使用了几个流行的dll的旧版本.它们与启动文件对话框并使用这些库的任何应用程序玩得很尽兴,因为外壳扩展将其dll加载到您的AppDomain中.到目前为止,我们唯一的解决方案是告诉用户卸载Dell Backup and Recovery.

Our app has the same problem. As you mentioned, the problem is that Dell Backup and Recovery installs a shell extension that uses old versions of several popular dlls. They play hell with any app that launches file dialogs and also uses those libraries, because shell extensions load their dlls into your AppDomain. The only solution we have so far is to tell the users to uninstall Dell Backup and Recovery.

如果您强制您的应用加载正确的库如dymanoid所述,那么您的应用程序在显示文件对话框时将崩溃(因为shell扩展名将崩溃).如果不这样做,那么当您尝试从数据库中读取应用程序时,该应用程序将崩溃.

If you force your app to load the correct library as dymanoid mentioned, then your app will crash when it displays a file dialog (because the shell extension will crash). If you don't do that, then your app will crash when it tries to read from its database.

有趣的是,戴尔备份与恢复是屡犯者;同时也打破QT5 办法.QT专家们的推荐的解决方案是用另一个名称编译您的QT库.-qtnamespace [名称]选项.我们也许可以使用system.data.sqlite来绑定类似的东西,但是随后我们必须编译自己的版本.

Interestingly, Dell Backup and Recovery is a repeat offender; it also breaks QT5 in the same way. The recommended solution from the QT guys is to compile your QT library under a different name with the -qtnamespace [name] option. We might be able to rig something like that with system.data.sqlite, but then we'd have to compile our own version.

Microsoft是

Microsoft is aware of the problem, but has declined to fix it.

我希望戴尔家伙实现了他们的外壳扩展像这样.

I wish the Dell guys had implemented their shell extension like this.

Portroit Pro AutoDesk解决此问题的方法还在于卸载Dell Backup and Recovery.

Portroit Pro, SONAR, and AutoDesk's solution to this problem is also to uninstall Dell Backup and Recovery.

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

A typical stack trace of the problem looks this in our application:

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的评论时,如果您想检测到此特定问题并给用户一些特别的提示,则可以执行以下操作:

So in answer to Track's comment, if you want to detect this particular problem and give the users some special notice, you could do something like this:

AppDomain.CurrentDomain.UnhandledException += UEHandler;
//...
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
  }
}

这篇关于使用SQLite的DLL地狱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆