在2台机器上生成的.tlh是不同的

时间:2009-05-26 16:02:10

标签: .net compiler-construction com interop typelib

我有一个.NET dll,它有一些暴露给com的接口\类。在构建过程中生成一个.tlb文件,这个tlb由一些c ++代码引用。因此,编译器为tlb生成.tlh文件。

当我在本地运行构建时,其中一个接口中的一个属性最终会在tlh中使用不具有相同名称的相应方法。 .net代码中的属性称为PropertyA,最终称为get_propertyA,而PropertyB最终称为get_PropertyB。当发生这种情况时我没有眨眼睛,只是使用了tlh中定义的方法,并假设一切都是笨拙的,但是当我编写这些更改时,构建对其他任何人都不起作用,因为编译器生成了名为get_PropertyA的属性, get_PropertyB(在propertyA中注意案例不匹配)。

两台机器上生成的tlb文件是相同的(根据十六进制比较器),tlh文件都是由相同的编译器版本生成的。

构建过程通过执行以下操作创建tlb:regasm path \ to \ dll \ Mydll.dll -tlb:path \ to \ output \ mydll.tlb

为什么我的本地版本最终会出现名称不正确的属性?或者我可以做些什么来解决它?

更新:我读到tlbexp将使用它找到的字符串的第一个版本,并且可以通过重新编译来更改。虽然我没有使用tlbexp,但我想知道这是不是问题。我找到了与我的方法同名的参数(在其他方法中),但在开头有一个小写字母。所以我替换了所有这些。重建,没有变化。所以我然后重命名了我的COM方法。重建并获得预期的丢失方法错误。将方法重命名为原始名称,嘿,它似乎是固定的。因为它现在似乎工作,我不能让它再次失败,我无法尝试建议的解决方案,但我喜欢重命名的想法,以防万一这种情况发生在将来。

3 个答案:

答案 0 :(得分:4)

您可以使用导入重命名属性来显式重命名属性。假设您有时propA PropApropB有时变为PropB。要始终PropAPropB使用重命名,如下所示:

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

小心使用它 - 它会导致一个简单的文本替换,适用于它在类型库中遇到的任何标识符。在某些情况下,它可能导致难以调试不良副作用。

答案 1 :(得分:4)

我遇到了同样的问题。

通过另一个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的类可能最终被公开为”monitor“首先遇到这样的名称。(并且只需重新编译程序集就可以改变遇到标识符的顺序!)/名称可以保证稳定的外壳。“

     

根本原因似乎是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)

     

名称文件包含定义如何进行capizalization的entriest。在我的情况下,它只包含一行:

     

ID

     

最好的问候

     

Bernd Ritter

使用/ names解决了这个问题。

答案 2 :(得分:0)

完整性检查:您是否绝对确定两台机器上都使用相同的#import指令?即正在编译的完全相同的源文件?

尝试在包含项目的目录上创建网络共享,并在另一台计算机上打开它,以便1000%确定这些是正在编译的源文件。

抱歉,我没有更具体的建议。