2009-05-26 11 views
6

Tengo una .NET dll que tiene algunas interfaces \ classes que están expuestas a com. durante el procedimiento de compilación, se genera un archivo .tlb y este tlb es referenciado por algún código de C++. Como resultado, el compilador genera un archivo .tlh para el tlb..tlh generado en 2 máquinas es diferente

Cuando ejecuto la compilación localmente una de las propiedades en una de las interfaces termina con un método correspondiente en la tlh que no tiene el mismo nombre. La propiedad en el código .net se llama PropertyA y se llama get_propertyA, mientras que PropertyB termina llamada get_PropertyB. No me puse a parpadear cuando esto sucedió, solo usé el método como se define en el tlh y asumí que todo era Hunky Dory, sin embargo, cuando comencé estos cambios la compilación no funcionó para nadie más, ya que el compilador generó propiedades llamadas get_PropertyA y get_PropertyB (desajuste de caso de aviso en propertyA).

Los archivos tlb generados en ambas máquinas son idénticos (según un comparador hexadecimal) y los archivos tlh son ambos generados por la misma versión del compilador.

El procedimiento de construcción crea la TLB haciendo: regasm ruta \ a \ dll \ Mydll.dll -tlb: ruta \ a \ salida \ mydll.tlb

¿Alguna idea de por qué mi versión local termina con una propiedad con el nombre incorrecto? ¿O qué puedo hacer para solucionarlo?

ACTUALIZACIÓN: He leído que tlbexp utilizará la primera versión de la cadena que encuentre y que puede cambiar con una recompilación. Aunque no estoy usando tlbexp, me pregunté si ese era el problema. Encontré parámetros con el mismo nombre que mi método (en otros métodos) pero con una letra minúscula al inicio. Así que reemplacé todos esos. Reconstruido, sin cambios. SO Entonces renombré mi método COM. Reconstruido y obtuvo los errores de método faltantes esperados. Renombrado el método de nuevo al nombre original, y listo, parecía fijo. Como ahora parece funcionar y no puedo hacer que vuelva a fallar, no puedo probar las soluciones sugeridas, pero me gusta la idea de cambiar el nombre en caso de que esto ocurra en el futuro.

+0

Tenga cuidado cuando use la solución alternativa de "cambio de nombre": funciona como una simple sustitución de texto y puede ocasionar resultados extraños a veces. He actualizado la respuesta para delinear eso. – sharptooth

+0

gracias por el aviso. Lo tendré en cuenta si surgen problemas. –

Respuesta

4

Puede utilizar el cambio de nombre atributo para la importación para cambiar el nombre explícitamente las propiedades. Digamos que tiene propA que a veces se convierte en PropA y propB que a veces se convierte en PropB. Tener siempre PropA y PropB uso cambiar el nombre de la siguiente manera:

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

Uso esto con cuidado - que causa un cambio de texto simple que funciona para cualquier identificador que encuentra en la biblioteca de tipos. En algunos casos, puede causar efectos secundarios no deseados difíciles de depurar.

+0

No se puede probar para ver si esto soluciona el problema (ver la actualización en la pregunta anterior) pero parece que probablemente no lo acepte como la respuesta, pero lo he votado a favor. Si el problema vuelve, lo intentaré y volveré.Gracias por la sugerencia –

+0

Ok, el problema volvió. Probé esto y parece funcionar bien. ¡Gracias! –

+0

No he votado negativamente ya que esto funciona, pero esto te obliga a hacer un cambio de nombre cada vez que importas la biblioteca. ¿No sería mejor forzar la creación correcta del tlb en primer lugar (ver/nombres en tlbexp) –

0

Comprobación de compatibilidad: ¿está absolutamente seguro de que se usa la misma directiva #import en ambas máquinas? es decir, los mismos archivos fuente exactos que se compilan?

Intente crear un recurso compartido de red sobre el directorio que contiene el proyecto y ábralo en la otra máquina para estar 1000% seguro de que estos son los mismos archivos fuente que se están compilando.

Lo siento, no tengo más sugerencias específicas.

+0

sí, hemos pasado por el control de cordura. Se están compilando los mismos archivos, hemos comprobado los números de versión de cvs. y hemos comprobado que los pasos intermedios producen los archivos correctos (los archivos tlb son idénticos) y las propiedades fueron recientemente introducidas (renombradas) en esta versión, por lo que el hecho de que estén apareciendo indica que está utilizando la fuente correcta. .. –

+0

¿Puedes publicar la línea de importación que estás usando? –

+0

# import raw_interfaces_only, raw_native_types, no_namespace, named_guids –

4

Estoy teniendo el mismo problema.

Via otra pregunta SO (https://stackoverflow.com/questions/708721/compare-type-libraries-generated-by-tlbexp) me encontré con este pedazo de contenido de la comunidad:

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

Citando de ese contenido:

En la documentación de TlbExp, hay una comunidad de utilidad contenido:

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

Cita:

"La razón de la opción/names es que las bibliotecas de tipos almacenan cada identificador en una tabla que no distingue entre mayúsculas y minúsculas. El primer caso encontrado gana. Entonces, una clase llamada Monitor podría terminar siendo expuesta como "monitor" si hay un parámetro con ese nombre encontrado primero. . (! Y el orden en que se encuentran los identificadores puede variar simplemente mediante la recompilación del montaje)/nombres pueden garantizar carcasa estable"

La causa parece ser un error en el midl, describe aquí:

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

Cita:

"Cuando hay dos identificadores que difieren sólo por caso, el caso de la segunda identificador se cambia para reflejar el caso de la primera"

Así como una solución, I unch seleccionó la opción "registrarse para interoperabilidad COM" en la configuración del proyecto y agregó los pasos posteriores a la compilación

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

el archivo contiene los nombres de la entriesthat definir cómo capizalization debe hacerse. En mi caso contiene sólo una línea:

ID

Saludos

Bernd Ritter

El uso de los nombres/ha resuelto este problema para mí.

+0

gracias por la actualización, a pesar de la vieja pregunta. +1 para un enfoque alternativo. –

Cuestiones relacionadas