DLL enfer avec SQLite

Certains de nos utilisateurs obtiennent un problème avec la version de sqlite.Interop.dll qui est chargé à l'exécution, et c'est un vrai casse-tête.

arrière-plan: Une application WPF construite pour AnyCPU, déployée avec SQlite .NET et sqlite.Interop.la version de la dll 1.0.89. Nous déployons à la fois x86 et x64 dlls et employons le chargement de retard inclus avec SQLite. Cela a été bien jusqu'à récemment, lorsque nous avons commencé à obtenir quelques problèmes de soutien de la part des utilisateurs qui avaient-généralement - récemment acheté de nouvelles machines Dell. Il semble qu'il existe une version plus ancienne de sqlite.Interop.dll (v. 1.0.80) que, en quelque sorte , est chargé de préférence à celui que nous expédions. L'erreur que nous obtenons est un point d'entrée manquant, 'sqlite3_changes_interop'.

Ce que nous avons essayé:

  1. changer la configuration pour simplement copier la dll appropriée (x86/64) dans le même répertoire que l'exécutable pendant l'installation (c.-à-d. pas de dossiers séparés x86/x64). Cela signifie que nous n'utilisons plus le chargement de delay, car la dll correcte est disponible dans le répertoire exécutable (bien que nous n'ayons pas désactivé explicitement le mécanisme de chargement de delay dans sqlite.net). Ça ne règle pas le problème..

  2. chargement explicite de sqlite.Interop.dll lorsque l'application se charge pour la première fois. Encore une fois, cela ne semble pas résoudre le problème.

il semble que l'ordre des lieux de chargement des dll a changé quelque peu au cours des dernières années, et je n'ai peut-être pas une bonne maîtrise de la situation. J'ai toujours supposé qu'une dll dans le répertoire exécutable obtiendrait la première préférence, et qu'une dll qui avait été explicitement chargée empêcherait la même dll d'être rechargée pendant la durée de vie de l'application, donc pour la vie de mon Je ne peux pas comprendre ce qui se passe ici.

est-ce que quelqu'un peut nous éclairer sur ce qui pourrait se passer ici? Le problème est en outre aggravé par le fait que je ne peux tout simplement pas reproduire le problème localement - par exemple en mettant la mauvaise version de la dll dans mon chemin système etc Ce qui me fait penser que peut-être le GAC pourrait entrer en jeu?

est vraiment coincé sur celui-ci, donc toute aide serait super.

aussi - comme dernier recours - je pourrais envisager de revenir à la même version 1.0.80, de sorte que nous ne recevons pas ce problème. Est-ce que quelqu'un sait où nous pourrions trouver des versions plus anciennes de sqlite.net et sqlite.Interop.dll?

Edit - quelques informations supplémentaires:

Le conflit est provoqué par une copie de sqlite.Interop.dll Version 1.0.80 qui est installé avec Dell Backup and Recovery. Ceci est installé sur toutes les nouvelles machines Dell, et les utilisateurs qui installent notre logiciel sur une telle machine font tous l'expérience de ce problème. Ce logiciel Dell utilise également le système.Données.SQLite.DLL.

la version correcte de sqlite.Interop.dll est situé dans le même répertoire que notre exécutable, et tout ce que je comprends sur le chargement dll suggère qu'il devrait être chargé de préférence.

bien que nous n'ayons pas encore pu reproduire la question localement, il semble que la mauvaise version d'interop.dll est et non sur le chemin. De plus, L'utilitaire Dell backup fonctionne automatiquement au démarrage. Personne ne sait de tout mécanisme par lequel cela pourrait être accrochage dll demandes de charge et de servir le mauvais fichier?

la pensée actuelle est que nous pourrions construire notre propre système.Données.SQLite.dll et changer le code de chargement interop en une version spécifiquement nommée (par exemple sqlite.Interop.1.0.89.DLL.) Pas une solution sympa d'aller de l'avant, mais..

20
demandé sur Matt 2015-06-14 22:57:37

3 réponses

notre application a le même problème. Comme vous l'avez mentionné, le problème est que Dell Backup and Recovery installe une extension shell qui utilise d'anciennes versions de plusieurs dlls populaires. Ils jouent l'enfer avec n'importe quelle application qui lance des dialogues de fichiers et utilise aussi ces bibliothèques, parce que les extensions de shell chargent leurs dlls dans votre Appdomaine. La seule solution que nous avons jusqu'à présent est de dire aux utilisateurs de désinstaller Dell Backup and Recovery.

si vous forcer votre application pour charger le corriger la bibliothèque comme dymanoid mentionné, alors votre application se plantera quand il affiche une boîte de dialogue de fichier (parce que l'extension shell se plantera). Si vous ne le faites pas, votre application se plantera quand elle essaiera de lire dans sa base de données.

fait intéressant, Dell Backup and Recovery est un récidiviste; il est également casse QT5 de la même manière. La solution recommandée par les gars de QT est de compiler votre bibliothèque QT sous un nom différent avec l'option-qtnamespace [nom]. On pourrait peut-être installer quelque chose comme ça avec le système.données.sqlite, mais ensuite nous devrions compiler notre propre version.

Microsoft conscient du problème , mais a refusé de le fixer.

j'aurais aimé que les gars de Dell aient implémenté leur extension shell comme ceci .

Sonar , et AutoDesk 's solution à ce problème est aussi de désinstaller Dell Backup and Recovery.

une trace de pile typique du problème regarde ceci dans notre 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()

donc en réponse au commentaire de Track, si vous voulez détecter ce problème particulier et donner aux utilisateurs un avis spécial, vous pouvez faire quelque chose comme ceci:

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
  }
}
11
répondu jcox 2017-05-23 12:25:24

SQLite.Interop.la dll est chargée de façon délicate.

En utilisant n'importe quel réflecteur, vous pouvez inspecter les méthodes non sécuritaires.Méthode Initialize () du Système.Données.SQLite.dll par vous-même.

Quelques notes pour démontrer, qu'il est possible d'obtenir quelque chose d'intéressant par réflexion (1.0.89 version):

  • If SQLite.Interop.dll est placé dans le répertoire de base - il sera chargé
  • preloadsqlite_basedirectory et Preloadsqlite_use_useassembly les variables d'environnement Directory peuvent affecter le processus de chargement
  • SQLite.Interop.dll peut être recherché dans les sous-dossiers prédifiés(x86, x64, Win32, Itanium, WinCE)
  • Trace.WriteLine est appelé à informer le chemin sélectionné (pas toujours)

le code Source est également disponible.

3
répondu FireAlkazar 2015-06-15 21:05:15

nous traitons exactement de cette question et la solution que nous avons trouvée est d'utiliser le paquet fourni par le système.Données.Site web SQlite plutôt que le paquet de nuget: https://system.data.sqlite.org/index.html/doc/trunk/www/downloads.wiki

la dll empaquetée a fusionné les assemblages managés et non managés de sorte qu'il n'est pas nécessaire de charger dynamiquement le Sqlite correct.Interop.dll de sorte que vous n'avez pas la question des versions contradictoires dans le domaine d'application.

lors de l'utilisation du bundled assembly vous devez inclure votre propre logique dans l'installateur de votre application pour décider quelle dll copier (x86 ou x64).

nous n'avons plus eu de problèmes avec les versions en conflit depuis l'utilisation de l'assemblage groupé.

1
répondu bvadala 2016-06-30 04:37:15