2009-05-26 11 views
6

Ho una DLL .NET che ha alcune interfacce \ classi che sono esposte a com. durante la procedura di compilazione viene generato un file .tlb e questo tlb viene fatto riferimento da qualche codice C++. Di conseguenza il compilatore genera un file .tlh per il tlb..tlh generato su 2 macchine è diverso

Quando eseguo il build localmente, una delle proprietà in una delle interfacce termina con un metodo corrispondente nel tlh che non ha lo stesso nome. La proprietà nel codice .net si chiama PropertyA finendo per essere chiamata get_propertyA, mentre PropertyB finisce con get_PropertyB. Non ho battuto ciglio quando questo è accaduto, ho solo usato il metodo come definito nel tlh e ho pensato che fosse tutto hunky dory, comunque quando ho apportato queste modifiche la build non ha funzionato per nessun altro, dato che il compilatore ha generato proprietà chiamate get_PropertyA e get_PropertyB (mancata corrispondenza tra maiuscole e minuscole nella proprietàA).

I file tlb generati su entrambe le macchine sono identici (in base a un confronto esadecimale) ei file tlh sono entrambi generati dalla stessa versione del compilatore.

La procedura di generazione crea il TLB facendo: regasm path \ to \ dll \ Mydll.dll -tlb: path \ to \ output \ mydll.tlb

Tutte le idee perché la mia versione locale finisce con una proprietà con il nome sbagliato? O cosa posso fare per risolverlo?

AGGIORNAMENTO: Ho letto che tlbexp userà la prima versione della stringa che trova e che può cambiare con una ricompilazione. Anche se non sto usando tlbexp, mi sono chiesto se fosse questo il problema. Ho trovato parametri con lo stesso nome del mio metodo (in altri metodi) ma con una lettera minuscola all'inizio. Così ho sostituito tutti quelli. Ricostruito, nessun cambiamento. Quindi ho rinominato il mio metodo COM. Ri-Costruito e ottenuto gli errori di metodo mancanti attesi. Ribattezzato il metodo con il nome originale, e presto è sembrato corretto. Visto che ora sembra funzionare e non riesco a far fallire di nuovo, non posso provare le soluzioni suggerite, ma mi piace l'idea di rinominare in caso ciò avvenga in futuro.

+0

Prestare attenzione quando si utilizza la soluzione "rinominare" - funziona come una semplice sostituzione di testo e può portare a risultati strani a volte. Ho aggiornato la risposta per delineare questo. – sharptooth

+0

grazie per l'heads up. Lo terrò a mente se emergono problemi. –

risposta

4

È possibile utilizzare il rename attributo per il importazione per rinominare in modo esplicito le proprietà. Supponiamo che tu abbia propA che a volte diventa PropA e propB che a volte diventa PropB. Per avere sempre PropA e PropB uso rinominare come segue:

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

Utilizzare questo con cura - provoca una semplice sostituzione di testo che funziona per qualsiasi identificatori che incontra nella libreria dei tipi. In alcuni casi può causare un difficile debug degli effetti collaterali indesiderati.

+0

Impossibile verificare se questo risolve il problema (vedere l'aggiornamento nella domanda precedente), ma sembra che probabilmente non possa accettare come risposta, ma l'ho svalutato. Se il problema si ripresenta, proverò e tornerò.Grazie per il suggerimento –

+0

Ok quindi il problema è tornato. Ho provato questo e sembra funzionare bene. Grazie! –

+0

Non ho effettuato il downvoting in quanto funziona, ma questo ti obbliga a rinominare ogni volta che importi la libreria. Non sarebbe meglio forzare la corretta creazione del tlb in primo luogo (vedi/nomi su tlbexp) –

0

Controllo di integrità: sei assolutamente sicuro che la stessa direttiva #import sia utilizzata su entrambe le macchine? vale a dire gli stessi file di origine esattamente compilati?

Provare a creare una condivisione di rete sulla directory contenente il progetto e aprirlo sull'altra macchina in modo da essere sicuro al 1000% che si tratti degli stessi file di origine in fase di compilazione.

Spiacente, non ho altri suggerimenti specifici.

+0

sì, abbiamo superato il controllo di integrità. Gli stessi file vengono compilati, abbiamo controllato i numeri di versione cvs. e abbiamo verificato che i passaggi intermedi producano i file corretti (i file tlb sono identici) e le proprietà sono state introdotte di recente (ridenominate) in questa versione, quindi il fatto che vengano visualizzate indica che sta utilizzando la giusta fonte. .. –

+0

Puoi pubblicare la linea #import che stai utilizzando? –

+0

#import raw_interfaces_only, raw_native_types, no_namespace, named_guids –

4

Ho lo stesso problema.

Via un'altra domanda SO (https://stackoverflow.com/questions/708721/compare-type-libraries-generated-by-tlbexp) ho trovato questo pezzo di contenuto comunità:

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

Citando dal contenuto:

Nella documentazione di TlbExp, c'è una comunità utile contenuto:

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

Offerta:

"Il motivo dell'opzione/names è che le librerie di tipi memorizzano ciascun identificatore in una tabella non sensibile al maiuscolo/minuscolo. Il primo caso riscontrato vince. Quindi una classe chiamata Monitor potrebbe finire per essere esposta come "monitor" se c'è un parametro con questo nome incontrato per primo. . (! E l'ordine in cui si riscontrano identificatori può variare semplicemente ricompilare il montaggio)/nomi possono garantire involucro stabile"

La causa principale sembra essere un bug nel MIDL, descritto qui:

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

Citazione:

"Quando ci sono due identificatori che differiscono solo per caso, il caso del secondo identificatore viene modificato in modo da riflettere il caso del primo"

Così come una soluzione, ho unch ha inserito l'opzione "registra per l'interoperabilità COM" nelle impostazioni del progetto e ha aggiunto i passaggi post-costruzione

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

il file contiene il nome entriesthat definire come capizalization dovrebbe essere fatto. Nel mio caso contiene solo una riga:

ID

migliori saluti

Bernd Ritter

Utilizzando i nomi/ha risolto questo problema per me.

+0

grazie per l'aggiornamento, nonostante la vecchia domanda. +1 per un approccio alternativo. –

Problemi correlati