.tlh генерируется на 2 машины разные - PullRequest
6 голосов
/ 26 мая 2009

У меня есть .NET dll, в которой есть некоторые интерфейсы \ классы, доступные для com. во время процедуры сборки создается файл .tlb, и на этот tlb ссылается некоторый код c ++. В результате компилятор генерирует файл .tlh для tlb.

Когда я запускаю сборку локально, одно из свойств в одном из интерфейсов заканчивается соответствующим методом в tlh, который не имеет того же имени. Свойство в .net-коде называется PropertyA и в конечном итоге называется get_propertyA, а PropertyB в конечном итоге называется get_PropertyB. Когда это произошло, я не разбивал веки, просто использовал метод, определенный в tlh, и предположил, что все было просто ужасно, но когда я внес эти изменения, сборка не сработала ни для кого другого, так как компилятор генерировал свойства с именем get_PropertyA get_PropertyB (обратите внимание на несоответствие регистра в свойстве A).

Файлы tlb, сгенерированные на обеих машинах, идентичны (согласно шестнадцатеричному компаратору), и оба файла tlh сгенерированы одной и той же версией компилятора.

Процедура сборки создает tlb, выполнив: regasm path \ to \ dll \ Mydll.dll -tlb: path \ to \ output \ mydll.tlb

Есть идеи, почему моя локальная версия имеет свойство с неправильным именем? Или что я могу сделать, чтобы это исправить?

ОБНОВЛЕНИЕ: я прочитал, что tlbexp будет использовать первую версию строки, которую он найдет и которая может измениться при перекомпиляции. Хотя я не использую tlbexp, я подумал, не в этом ли проблема. Я нашел параметры с тем же именем, что и у моего метода (в других методах), но с заглавной буквы в начале. Поэтому я заменил все это. Перестроен, без изменений. Поэтому я переименовал свой метод COM. Перестроен и получил ожидаемые ошибки метода. Переименовал метод обратно в исходное имя, и, эй, до того, как он выглядел исправленным. Поскольку теперь это работает, и я не могу заставить его снова выйти из строя, я не могу попробовать предложенные решения, но мне нравится идея переименования в случае, если это произойдет в будущем.

Ответы [ 3 ]

4 голосов
/ 27 мая 2009

Вы можете использовать атрибут rename для import , чтобы явно переименовать свойства. Скажем, у вас есть propA, который иногда становится PropA и propB, который иногда становится PropB. Чтобы всегда иметь PropA и PropB, используйте переименуйте следующим образом:

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

Используйте это с осторожностью - это вызывает простую подстановку текста, которая работает для любых идентификаторов, которые встречаются в библиотеке типов. В некоторых случаях это может вызвать затруднения при отладке нежелательных побочных эффектов.

4 голосов
/ 09 июня 2010

У меня та же проблема.

Через другой вопрос SO (https://stackoverflow.com/questions/708721/compare-type-libraries-generated-by-tlbexp) я нашел этот фрагмент контента сообщества:

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

Цитата из этого содержания:

В документации по tlbexp есть одно полезное содержимое сообщества:

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

Цитата:

"Причина для параметра / names заключается в том, что библиотеки типов хранят каждый идентификатор в таблице без учета регистра. Первый случай, в котором встречаются, побеждает. Таким образом, класс с именем Monitor может оказаться в качестве" монитора ", если есть параметр с такое имя встречается первым. (И порядок, в котором встречаются идентификаторы, может измениться просто путем перекомпиляции вашей сборки!) / names может гарантировать стабильный регистр. "

Основной причиной является ошибка в midl, описанная здесь:

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

Цитата:

"Когда есть два идентификатора, которые отличаются только регистром, регистр второго идентификатора изменяется, чтобы отразить регистр первого."

В качестве решения я снял флажок «зарегистрироваться для COM-взаимодействия» в настройках проекта и добавил шаги после сборки

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

Файл имен содержит записи, которые определяют, как должна выполняться капитализация. В моем случае он содержит только одну строку:

ID

С наилучшими пожеланиями

Бернд Риттер

Использование / names решило эту проблему для меня.

0 голосов
/ 26 мая 2009

Проверка работоспособности: вы абсолютно уверены, что одна и та же директива #import используется на обеих машинах? то есть одни и те же исходные файлы, которые компилируются?

Попробуйте создать сетевой ресурс над каталогом, содержащим проект, и откройте его на другом компьютере, чтобы на 1000% убедиться, что это те же исходные файлы, которые компилируются.

Извините, у меня нет более конкретных предложений.

...