7
votes

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?

2

2 Answers

7
votes

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.

1
votes

Take a look at the new customizable tlbimp tool:

https://blogs.msdn.microsoft.com/dotnet/2009/03/19/new-tlbimp-release-on-codeplex-full-customization-of-interop-assemblies/

Ruled-based customization of interop assemblies

The new TlbImp utility allows users to customize the interop assembly conversion process within TlbImp, by specifying a set of rules to customize specified types/functions/signature. We’ve received a lot of feedback from TlbImp users that they want the ability to make their own changes to the interop assembly in their build process, and they end up using ILDASM to disassemble the interop assembly into IL code, modify it using a PERL script, and then use ILASM to re-generate the interop assembly. This is obviously a painful process and requires a lot of additional work. This feature is designed to solve this problem.

Regression Test Tool

In order to help developers to make sure his change doesn’t cause any regression, we’ve developed a simple regression test tool