Friday, February 17, 2012

Implementing a VB6 COM interface in VB.Net - it's not all roses!

Not long after my revelation last week, that VB.Net could implement my VB6 COM interface that had a "optional string" parameter, I ran into a brick wall: VB.Net cannot implement a COM interface where a "Public Property" that passes variables by-reference has been exposed. ie. it can't implement this VB6 code:

Public Property Let MyProperty(sValue As String)
End Property

Try it and you get the following error:

Implementing property must have matching 'ReadOnly' or 'WriteOnly' specifiers.

This is a known bug and the only solution is to modify your COM interface (in your original VB6 dll) so that the arguments are passed by-value:

Public Property Let MyProperty(ByVal sValue As String)
End Property

Which, under the covers, changes the COM interface from:

[id(0x68030000), propput]
HRESULT MyProperty([in, out] BSTR* );


[id(0x68030000), propput]
HRESULT MyProperty([in] BSTR );

But of course, I don't want to change the COM interface - I want to implement the interface that has already been defined and is already being used by multiple legacy applications.

Or I can use C#, which handles these Public Properties just fine.

So I'm caught in a bind - only C# can handle the Public Properties, and only VB.Net can handle the Optional String Parameters. I'm going to have to break my COM interface and force multiple client recompilations... OR use a VB6 COM facade that calls my .Net dll.

A tough choice - yuck, yucky, or yuckier?