C # to C++/CLI to C DLL System.IO.FileNotFoundException
i'm getting System.IO.FileNotFoundException: The specified module could not be found
" quand on exécute le code C qui appelle une Assemblée C++/CLI qui à son tour appelle un C DLL pur. Il se produit dès qu'un objet est instancié qui appelle les fonctions pures de DLL.
BackingStore est pur C. CPPDemoViewModel est C++ / CLI appelant BackingStore il a une référence à BackingStore.
j'ai essayé le cas le plus simple possible-Ajouter un nouveau C# Unité de test projet qui tente juste de créer un objet défini dans CPPDemoViewModel . J'ai ajouté une référence du projet C# à CPPDemoViewModel .
un projet de test C++/CLI fonctionne très bien avec juste la réf ajoutée à CPPDemoViewModel donc c'est quelque chose à propos de passer entre les langues.
J'utilise Visual Studio 2008 SP1 avec .Net 3.5 SP1. Je m'appuie sur Vista x64 mais j'ai pris soin de m'assurer que ma cible de plate-forme est réglée sur x86.
cela ressemble à quelque chose de stupide et c'est évident que je manque mais ce serait encore plus stupide de ma part de perdre du temps à essayer de le résoudre en privé donc je suis ici à m'embarrasser moi-même!
ceci est un test pour un projet portant une énorme quantité de code C legacy que je garde dans une DLL avec un ViewModel implémenté en C++/CLI.
modifier Après avoir vérifié les répertoires, je peux confirmer que la BackingStore.dll n'a pas été copié.
j'ai la norme dossiers de projets uniques créés avec une solution multi-projets typique.
WPFViewModelInCPP BackingStore CPPViewModel CPPViewModelTestInCS bin Debug Debug
le débogage de haut niveau semble être un dossier courant utilisé par les projets C et C++/CLI, à ma grande surprise.
WPFViewModelInCPPDebug contient BackingStore.dll, CPPDemoViewModel.dll, CPPViewModelTest.dll et leur associés .ilk et .fichiers de l'APB
WPFViewModelInCPPCppviewmodeltincsbinDebug contient CPPDemoViewModel et Cppviewmodeltestinchs .dll et .fichiers pdb mais pas BackingStore. Cependant, copier manuellement BackingStore dans ce répertoire n'a pas corrigé l'erreur.
CPPDemoViewModel a la propriété copier Local ensemble qui je suppose est responsable de copier sa DLL quand si est référencé. Je ne peux pas ajouter une référence d'un projet C# à un C DLL pur - il dit juste une référence au magasin de soutien pourrait pas être ajouté.
Je ne suis pas sûr d'avoir juste un problème ou deux.
je peux utiliser une ancienne étape de construction de copie pour copier le BackingStore.dll dans tous les répertoires du projet C#, même si j'espérais que le nouveau modèle .net n'en aurait pas besoin.
DependencyWalker me dit que le fichier manquant est GPSVC.dll qui a été suggéré indique des problèmes de réglage de la sécurité. Je soupçonne c'est un leurre.
edit2 Avec une copie manuelle de BackingStore.dll à côté de l'exécutable, l'interface graphique fonctionne maintenant très bien. Le projet de Test C# a encore des problèmes que je soupçonne être dus à l'environnement d'exécution d'un projet de test, mais je peux vivre sans cela pour le moment.
6 réponses
les DLLs C et C++ sont-ils dans le même répertoire que L'Assemblée C# qui s'exécute?
vous devrez peut-être modifier les paramètres de sortie de votre projet pour que le C# assembly et les autres DLLs finissent tous dans le même dossier.
j'ai souvent utilisé le Dependency Walker dans des cas comme celui-ci; c'est un contrôle de santé mentale qui montre que toutes les dépendances peuvent effectivement être trouvées.
une Fois que votre application est en cours d'exécution, vous peut également vouloir essayer Process Monitor sur le code que vous exécutez, pour voir quels DLLs sont référencés, et où ils sont situés.
la réponse pour L'interface graphique, autre que la modification des paramètres de sortie, a été l'ajout d'une étape de pré-construction
copy $(ProjectDir)..\Debug\BackingStore.* $(TargetDir)
la réponse pour les projets de Test était d'ajouter la DLL manquante à L'onglet déploiement du testrunconfig. Vous pouvez soit le faire en éditant directement la valeur par défaut LocalTestRun.testrunconfig (apparaît en Solution sous les éléments de la Solution) ou cliquez avec le bouton droit de la souris sur la Solution et ajoutez une nouvelle configuration de test run, qui apparaîtra ensuite sous le menu de Test principal.
Merci pour les réponses sur cette SO question sur les configurations d'essai pour me conduire à la réponse.
la raison pour laquelle cela se produit est parce que vous chargez DLLMAIN à partir du code géré, avant que le CRT ait une opportunité d'être initialisé. Vous ne pouvez pas avoir de code géré, être exécuté directement ou indécemment à partir d'un effet de notifications de DllMain. (Voir: Expert C++ / CLI: .Net for Visual C++ Programmers, chapitre 11++).
ou vous n'avez aucun point d'entrée natif défini wahtstoever, pourtant vous avez lié MSVCRT. Le CLR est automatiquement initialisé pour vous avec / clr, ce détail provoque beaucoup de confusion et doit être pris en compte. Un DLL mode mixte en fait delay loads le CLR à travers l'utilisation de Hot-patching tout le point d'entrée géré vtables dans vos classes.
un certain nombre de problèmes d'initialisation de classe entourent ce sujet, loader lock et Delay loading CLR sont un peu compliqués parfois. Essayez de déclarer global statique et ne pas utiliser # pragma managed / unmanaged, isolez votre code avec /clr per-file.
si vous ne pouvez pas isoler votre code du code géré, et que vous avez des problèmes, (après avoir pris certaines de ces mesures), vous pouvez également envisager d'héberger le CLR vous-même et peut-être passer par l'effort de créer un gestionnaire de domaine, qui assurerait votre entièrement" dans la boucle " des événements runtime et bootstrapping.
c'est exactement pourquoi, il n'a rien faire avec votre recherche chemin, ou initialisation. Malheureusement, la visionneuse de journaux de Fusion n'aide pas beaucoup (ce qui est l'endroit habituel pour rechercher.CLR assembly binding issues not dependency walker).
Lier statiquement n'a rien todo avec ce soit. Vous pouvez pas lier statiquement une application C++/CLI qui est en mode mixte.
- Placez votre fonction DLLMAIN dans un fichier par elle-même.
- S'assurer que ce fichier ne PAS ont /CLR dans les options de compilation ( fichier options de compilation)
- assurez-vous que votre lien avec /MD ou /MDd, et toutes vos dépendances que vous liez utilisent le même CRT.
- évaluer les paramètres de votre linker pour / DEFAULTLIB et / INCLUDE pour identifier tout problème de référence possible, vous pouvez déclarer un prototype dans votre code et utiliser / INCLUDE pour outrepasser la valeur par défaut résolution des liens de la bibliothèque.
Bonne chance, vérifiez aussi que le livre c'est du très bon.
C'est un dilemme intéressant. Je n'ai jamais entendu parler d'un problème de chargement natif .Dll à partir de C++/CLI, après un appel à partir de C# avant. Je ne peux que supposer que le problème est comme @Daniel l suggéré, et que votre .DLL n'est tout simplement pas dans un chemin que le chargeur d'assemblage peut trouver.
si la suggestion de Daniel ne fonctionne pas, je vous suggère d'essayer de lier statiquement le code C natif au programme C++/CLI, si vous le pouvez. Cela résoudrait certainement le problème, comme le .DLL serait alors entièrement absorbé dans le C++/CLI .DLL.
assurez-vous que le système cible a le bon MS Visual C runtime, et que vous ne construisez pas accidentellement le dll C avec un debug runtime.
a eu le même problème en passant à 64-bit Vista. Notre application appelait Win32 DLLs qui déroutait la construction de la cible pour l'application. Pour le résoudre, nous avons fait ce qui suit:
- Allez à propriétés de projet;
- sélectionnez L'onglet Construire;
- Changement " Plate-forme cible:' option pour x86;
- reconstruire l'application.
Quand j'ai relancé l'application, il travaillé.