Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.tlh generated on 2 machines is different

I have a .NET dll which has some interfaces\classes which are exposed to com. during the build procedure a .tlb file is generated and this tlb is referenced by some c++ code. As a result the compiler generates a .tlh file for the tlb.

When I run the build locally one of the properties in one of the interfaces ends up with a corresponding method in the tlh which does not have the same name. The property in the .net code is called PropertyA end up being called get_propertyA, while PropertyB ends up called get_PropertyB. I didn't bat an eyelid when this happened, just used the method as defined in the tlh and assumed everything was hunky dory, however when I comitted these changes the build did not work for anyone else, as the compiler generated properties called get_PropertyA and get_PropertyB (notice case mismatch in propertyA).

The tlb files generated on both machines are identical (according to a hex comparer) and the tlh files are both generated by the same compiler version.

The build procedure creates the tlb by doing: regasm path\to\dll\Mydll.dll -tlb:path\to\output\mydll.tlb

Any ideas why my local version ends up with a property with the incorrect name? Or what I can do to fix it?

UPDATE: I read that tlbexp will use the first version of the string that it finds and that can change with a recompile. Although I'm not using tlbexp, I wondered if that was the problem. I found parameters with the same name as my method (in other methods) but with a lower case letter at the start. So I replaced all of those. Re-built, no change. SO I then renamed my COM method. Re-Built and got the expected missing method errors. Renamed the method back to the original name, and hey presto it seemed fixed. As it now seems to work and I can't get it to fail again I can't try out the suggested solutions, but I like the rename idea in case this happens in the future.

like image 714
Sam Holder Avatar asked May 26 '09 16:05

Sam Holder


2 Answers

I'm having the same problem.

Via another SO question ( https://stackoverflow.com/questions/708721/compare-type-libraries-generated-by-tlbexp ) I found this piece of community content:

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

Quoting from that content:

In the documentation of tlbexp, there is one useful community content:

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

Quote:

"The reason for the /names option is that type libraries store each identifier in a case-insensitive table. The first case encountered wins. So a class called Monitor might end up being exposed as "monitor" if there's a parameter with such a name encountered first. (And the order in which identifiers are encountered can vary simply by recompiling your assembly!) /names can guarantee stable casing."

The root cause seems to be a bug in the midl, described here:

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

Quote:

"When there are two identifiers that differ only by case, the case of the second identifier is changed to reflect the case of the first."

So as a solution, I unchecked the option "register for COM interop" in the project settings and added the post-build-steps

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

The names file contains the entriesthat define how capizalization should be done. In my case it contains only one line:

ID

Best Regards

Bernd Ritter

Using the /names has solved this problem for me.

like image 129
Ed Sykes Avatar answered Nov 09 '22 01:11

Ed Sykes


You can use the rename attribute for the import to explicitly rename the properties. Say you have propA that sometimes becomes PropA and propB that sometimes becomes PropB. To always have PropA and PropB use rename as follows:

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

Use this with care - it causes a simple text substitution that works for any identifiers it encounters in the type library. In some cases it can cause hard to debug undesired side effects.

like image 28
sharptooth Avatar answered Nov 09 '22 01:11

sharptooth