views:

96

answers:

3

I have a VC++ COM component with a type library. The type library of this component declares an interface and a co-class:

[
    object,
    uuid( ActualUuidHere),
    dual,
    nonextensible,
    oleautomation,
    hidden,
    helpstring( ActualHelpStringHere )
]
interface IWorkflow : IDispatch 
{
    //irrelevant properties here    
}

[
    uuid(ActualClassIdHere),
    noncreatable
]
coclass Workflow {
    [default] interface IWorkflow;
};

In order to consume the component from a C# application I add a reference to the C# project and an interop assembly is generated.

In the Object Browser of Visual Studio 2003 I see that the interop contains:

public abstract interface IWorkflow;
public abstract interface workflow : IWorkflow;
public class workflowClass : System.Object;

It's clear that that for some reason the name of the class and the interface differ in capitalization. This doesn't happen for other 20+ interfaces declared in the same type library - for them ISomething corresponds to Something and SomethingClass.

I've looked through the .idl files of the project - the identifier Workflow is not used anywhere else.

What's the reason of this strange behaviour and how can it be worked around?

A: 

Take a look at the new customizable tlbimp tool on CodePlex:

http://blogs.msdn.com/clrteam/archive/2009/03/19/new-tlbimp-release-on-codeplex-full-customization-of-interop-assemblies.aspx

280Z28
+1  A: 

Look through your code and see if there is any parameter, property, or method name which has the exact spelling and capitalization of "workflow". It will almost certainly be a parameter to a COM interface function. Change the name to be paramWorkflow and your problem should go away.

Why does this happen? There is a bug in the type library tools where they will store identifiers in a case insensitive fashion internally. So if you have two names with different capatilization they will be stored in the same slot. These names are then directly used at generation time so the different casing will be emitted.

The way to work around this is to prevent the conflict by creating different names.

JaredPar
Looked through all the IDL files in the project - the name is not used anywhere else.
sharptooth
Thanks. I was having this problem, and your solution fixed it.
Groky
A: 

Yup-- this really happens. We had a property with a given name, and a parameter to another method that was changed and then collided. Same name, different casing-- wham. To make things even more interesting, we have two build targets, and something was juuuuuust different enough about the build order that we got one capitalization in one-- which worked-- and the other in the other-- which failed. Real fun when both projects check out the same source and .sln files, etc. What a blast tracking that one down.

Matt Neck