Question

Je reçois System.IO.FileNotFoundException: le module spécifié est introuvable lors de l'exécution d'un code C # appelant un assembly C ++ / CLI qui appelle à son tour un DLL C pure. Cela se produit dès qu’un objet instancié appelle les fonctions de la DLL C pure.

BackingStore est un C pur. CPPDemoViewModel est C ++ / CLI appelant BackingStore, il contient une référence à BackingStore.

J'ai essayé le cas le plus simple possible: ajoutez un nouveau projet de test d'unité C # qui tente simplement 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 correctement avec juste la référence ajoutée à CPPDemoViewModel, il s'agit donc de passer d'une langue à l'autre.

J'utilise Visual Studio 2008 SP1 avec .Net 3.5 SP1. Je travaille sous Vista x64, mais j’ai veillé à ce que ma cible Platform soit définie sur x86.

Cela me semble être quelque chose de stupide et évident mais il serait encore plus stupide de ma part de perdre du temps à essayer de le résoudre en privé, alors je me suis embarrassée ici!

Il s'agit d'un test pour un projet portant une énorme quantité de code C hérité que je conserve dans une DLL avec un ViewModel implémenté en C ++ / CLI.

modifier Après avoir vérifié les répertoires, je peux confirmer que le BackingStore.dll n’a pas été copié.

J'ai les dossiers de projets uniques standard créés avec une solution multi-projets typique.

WPFViewModelInCPP
  BackingStore
  CPPViewModel
  CPPViewModelTestInCS
    bin
      Debug
  Debug

Le débogage de niveau supérieur semble être un dossier commun utilisé par les projets C et C ++ / CLI, à ma grande surprise.

WPFViewModelInCPP \ Debug contient les fichiers BackingStore.dll, CPPDemoViewModel.dll, CPPViewModelTest.dll et leurs fichiers .ilk et .pdb associés

WPFViewModelInCPP \ CPPViewModelTestInCS \ bin \ Debug contient les fichiers CPPDemoViewModel et CPPViewModelTestInCS, ainsi que pas BackingStore. Toutefois, la copie manuelle de BackingStore dans ce répertoire n'a pas corrigé l'erreur.

CPPDemoViewModel a la propriété Copie locale définie. Je suppose qu'elle est responsable de la copie de sa DLL lorsque if est référencé. Je ne peux pas ajouter une référence d'un projet C # à une DLL C pure. Elle indique simplement: Une référence à la sauvegarde du magasin n'a pas pu être ajoutée.

Je ne sais pas si j'ai juste un ou deux problèmes.

Je peux utiliser une étape de compilation à l'ancienne pour copier le BackingStore.dll dans n'importe quel répertoire de projet C #, bien que j'espérais que le nouveau modèle .net n'exigeait pas cela.

DependencyWalker me dit que le fichier manquant est GPSVC.dll, ce qui a été suggéré pour indique les problèmes de paramètres de sécurité. Je soupçonne que c'est un hareng rouge.

modifier2 Avec une copie manuelle de BackingStore.dll adjacente à l'exécutable, l'interface graphique fonctionne désormais correctement. Le projet de test C # a toujours des problèmes que je soupçonne d'être dus à l'environnement d'exécution d'un projet de test, mais je peux vivre sans cela pour l'instant.

Était-ce utile?

La solution 2

La réponse de 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 solution pour les projets de test consistait à ajouter la DLL manquante à l'onglet Déploiement du testrunconfig. Vous pouvez le faire en modifiant directement le LocalTestRun.testrunconfig par défaut (affiché dans la solution sous Éléments de solution) ou en cliquant avec le bouton droit de la souris sur la solution et en ajoutant une nouvelle configuration, qui apparaîtra ensuite sous le test principal. menu.

Merci pour les réponses apportées à la question SO 57 sur les configurations de test. pour me conduire à la réponse.

Autres conseils

Les DLL C et C ++ sont-elles dans le même répertoire que l'assembly C # en cours d'exécution?

Vous devrez peut-être modifier les paramètres de sortie de votre projet pour que l'assemblage C # et les autres DLL se retrouvent tous dans le même dossier.

J'ai souvent utilisé Dependency Walker dans des cas comme celui-ci; c'est un test de bon sens qui montre que toutes les dépendances peuvent effectivement être trouvées.

Une fois votre application en cours d'exécution, vous pouvez également essayer Moniteur de processus sur le code que vous utilisez, pour voir quelles DLL sont référencées et où elles se trouvent.

Cela s’explique par le fait que vous devez soit charger DLLMAIN à partir du code managé, avant que le CRT puisse être initialisé. Vous pouvez ne pas avoir de code géré, être exécuté DIRECTEMENT ou INDÉRECTÉMENT à partir d'un effet de notifications DllMain. (Voir: Expert C ++ / CLI: Programmeurs .Net pour Visual C ++, chapitre 11 ++).

Ou vous n’avez pas de point d’entrée natif défini wahtsoever, mais vous vous êtes lié à MSVCRT. Le CLR est automatiquement initialisé pour vous avec / clr, ce détail cause beaucoup de confusion et doit être pris en compte. En réalité, une DLL en mode mixte retarde le chargement du CLR par l’utilisation de correctifs à chaud pour tous les vtables de points d’entrée gérés dans vos classes.

Un certain nombre de problèmes d’initialisation de classe concernent ce sujet, le verrouillage du chargeur et le retard du chargement du CLR sont parfois un peu compliqués. Essayez de déclarer le statique de global sans utiliser #pragma managed / unmanaged, isolez votre code avec / clr par fichier.

Si vous ne parvenez pas à isoler votre code du code géré et rencontrez des difficultés (après avoir suivi certaines de ces étapes), vous pouvez également envisager d’héberger vous-même le CLR et éventuellement de créer un gestionnaire de domaine, cela vous assurerait pleinement "dans la boucle". des événements d'exécution et du démarrage.

C’est précisément pour cela qu’il n’a rien à faire avec votre chemin de recherche ou votre initialisation. Malheureusement, le visualiseur de journal Fusion n’aide pas beaucoup (ce qui est l’endroit habituel pour rechercher des problèmes de liaison d’assemblages .NET CLR et non de dépendances).

La liaison statique n’a rien à faire avec cela non plus. Vous pouvez NOT relier statiquement une application C ++ / CLI en mode mixte.

  1. Placez votre fonction DLLMAIN dans un fichier à part.
  2. Assurez-vous que SAUF ne contient pas / CLR dans les options de génération de ce fichier ( fichier options de construction)
  3. Assurez-vous que votre liaison avec / MD ou / MDd et toutes vos dépendances que vous LIEN utilisent exactement le même tube cathodique.
  4. Evaluez les paramètres de votre éditeur de liens pour / DEFAULTLIB et / INCLUDE afin d'identifier tout problème de référence possible, vous pouvez déclarer un prototype dans votre code et utiliser / INCLUDE pour remplacer la résolution du lien de bibliothèque par défaut.

Bonne chance, vérifiez également que le livre est très bon.

C’est un dilemme intéressant. Je n'ai jamais entendu parler d'un problème de chargement de fichiers .DLL natifs à partir de C ++ / CLI après un appel de C # auparavant. Je ne peux que supposer que le problème est lié au @Daniel L suggéré, et que votre fichier .DLL ne se trouve tout simplement pas dans un chemin que le chargeur d'assemblages 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, car le fichier .DLL serait alors entièrement absorbé dans le fichier C ++ / CLI .DLL.

Assurez-vous que le système cible a le bon runtime MS Visual C et que vous ne construisez pas accidentellement la dll C avec un runtime de débogage.

Vous avez eu le même problème lors du basculement vers Vista 64 bits. Notre application appelait des DLL Win32, ce qui confondait la génération cible pour l'application. Pour résoudre ce problème, nous avons procédé comme suit:

  1. Accéder aux propriétés du projet;
  2. Sélectionnez l'onglet Construire;
  3. Changer l'option 'Cible de la plateforme:' en x86;
  4. Reconstruisez l'application.

Lorsque j'ai ré-exécuté l'application, cela a fonctionné.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top