2009-05-26 6 views
6

J'ai une DLL .NET qui a quelques interfaces \ classes qui sont exposées à com. Au cours de la procédure de construction, un fichier .tlb est généré et cette tlb est référencée par du code C++. Par conséquent, le compilateur génère un fichier .tlh pour la tlb..tlh généré sur 2 machines est différent

Lorsque je lance la construction localement, l'une des propriétés de l'une des interfaces se termine par une méthode correspondante dans le tlh qui n'a pas le même nom. La propriété dans le code .net s'appelle PropertyA et s'appelle get_propertyA, tandis que PropertyB se termine par get_PropertyB. Je n'ai pas battu une paupière quand cela s'est produit, j'ai simplement utilisé la méthode telle que définie dans le tlh et supposé que tout était hunky dory, cependant quand j'ai coché ces changements, la construction ne fonctionnait pas pour quelqu'un d'autre, car le compilateur produisait get_PropertyA et get_PropertyB (discordance de cas de notification dans la propriété A).

Les fichiers tlb générés sur les deux machines sont identiques (d'après un comparateur) et les fichiers tlh sont générés par la même version du compilateur.

La procédure de construction crée le TLB en faisant: chemin regasm \ à \ dll \ Mydll.dll -tlb: path \ to \ output \ mydll.tlb

Toutes les idées pourquoi ma version locale se termine avec une propriété avec le nom incorrect? Ou ce que je peux faire pour le réparer? MISE À JOUR: J'ai lu que tlbexp utilisera la première version de la chaîne qu'il trouve et qui peut changer avec une recompilation. Bien que je n'utilise pas tlbexp, je me demandais si c'était le problème. J'ai trouvé des paramètres avec le même nom que ma méthode (dans d'autres méthodes) mais avec une lettre minuscule au début. Alors j'ai remplacé tous ceux-là. Reconstruit, pas de changement. SO j'ai alors renommé ma méthode COM. Re-Built et obtenu les erreurs de méthode manquantes attendues. Rebaptisé la méthode au nom d'origine, et hey presto il semblait fixe. Comme il semble maintenant fonctionner et je ne peux pas l'échouer à nouveau je ne peux pas essayer les solutions suggérées, mais j'aime l'idée de renommer au cas où cela se produirait dans le futur.

+0

Faites attention lorsque vous utilisez la solution de contournement "renommer" - cela fonctionne comme une simple substitution de texte et peut parfois conduire à des résultats bizarres. J'ai mis à jour la réponse pour décrire cela. – sharptooth

+0

merci pour les heads up. Je garderai cela à l'esprit si des problèmes surviennent. –

Répondre

4

Vous pouvez utiliser l'attribut renommer pour importer pour renommer explicitement les propriétés. Supposons que vous ayez propA qui devient parfois PropA et propB qui devient parfois PropB. Pour avoir toujours PropA et PropB utilisation renommer comme suit:

#import <library> rename("propA", "PropA") rename("propB", "PropB") 

Utilisez ce avec soin - il provoque une substitution de texte simple qui fonctionne pour tous les identificateurs qu'il rencontre dans la bibliothèque de type. Dans certains cas, il peut être difficile de déboguer des effets secondaires indésirables.

+0

Impossible de tester si cela résout le problème (voir mise à jour en question ci-dessus), mais il semble que cela ne puisse probablement pas être accepté comme réponse, mais je l'ai upvoted. Si le problème revient, je vais essayer et revenir.Merci pour la suggestion –

+0

Ok, donc le problème est revenu. J'ai testé cela et cela semble bien fonctionner. Merci! –

+0

Je n'ai pas downvote car cela fonctionne, mais cela vous oblige à renommer chaque fois que vous importez la bibliothèque. Ne serait-il pas préférable de forcer la bonne création de la tlb en premier lieu (voir/noms sur tlbexp) –

0

Contrôle d'intégrité: êtes-vous absolument certain que la même directive #import est utilisée sur les deux machines? c'est-à-dire les mêmes fichiers source exactement en cours de compilation? Essayez de créer un partage réseau sur le répertoire contenant le projet et ouvrez-le sur l'autre machine afin d'être sûr à 100% que ce sont les mêmes fichiers source en cours de compilation.

Désolé, je n'ai pas de suggestion plus précise.

+0

oui, nous avons été à travers le contrôle de santé mentale. Les mêmes fichiers sont en cours de compilation, nous avons vérifié les numéros de version cvs. et nous avons vérifié que les étapes intermédiaires produisent les fichiers corrects (les fichiers tlb sont identiques) et que les propriétés ont été nouvellement introduites (renommées) dans cette version, donc le fait qu'elles apparaissent indique qu'elles utilisent la bonne source. –

+0

Pouvez-vous poster la ligne # import que vous utilisez? –

+0

#import raw_interfaces_only, raw_native_types, no_namespace, named_guids –

4

J'ai le même problème.

Via une autre question SO (https://stackoverflow.com/questions/708721/compare-type-libraries-generated-by-tlbexp) J'ai trouvé ce morceau de contenu communautaire:

http://social.msdn.microsoft.com/Forums/en-US/clr/thread/5003c486-ed3f-4ec8-8398-a1251b0f9e74

Je cite ce contenu:

Dans la documentation de TlbExp, il y a une communauté utile contenu:

http://msdn2.microsoft.com/en-gb/library/hfzzah2c(VS.80).aspx

Citation:

"La raison de l'option/names est que les bibliothèques de types stockent chaque identificateur dans une table insensible à la casse. Le premier cas rencontré gagne. Ainsi, une classe appelée Monitor peut être exposée comme "monitor" si un paramètre avec un tel nom est rencontré en premier. . (! Et l'ordre dans lequel les identificateurs sont rencontrés peuvent varier simplement en recompiler votre assemblée)/noms peuvent garantir boîtier stable »

La cause semble être un bug dans le midl, décrit ici:

http://support.microsoft.com/default.aspx?scid=kb;en-us;220137

Quote:

«Quand il y a deux identifiants qui ne diffèrent que par cas, le cas du second identifiant est modifié pour refléter le cas de la première »

donc comme une solution, je unch a coché l'option "register for COM interop" dans les paramètres du projet et ajouté les étapes post-construction

"$ (DevEnvDir) .... \ SDK \ v2.0 \ Bin \ tlbexp" $ (TargetFileName)/noms: "$ (ProjectDir) Names.txt" % windir% \ Microsoft.NET \ Framework \ v2.0.50727 \ regasm $ (TargetFileName)

Le fichier de noms contient les entrées qui définissent la façon dont la personnalisation doit être effectuée. Dans mon cas, il ne contient qu'une seule ligne:

ID

Cordialement

Bernd Ritter

En utilisant les noms/a résolu ce problème pour moi.

+0

merci pour la mise à jour, malgré l'ancienne question. +1 pour une approche alternative. –

Questions connexes