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.
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.
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.
Sanity check: are you absolutely sure the same #import directive is used on both machines? i.e. the same exactly source files being compiled?
Try creating a network share over the directory containing the project and open it on the other machine in order to be 1000% sure these are the same source files being compiled.
Sorry I don't have any more specific suggestions.