1

Let's assume

  • I'm working for company A and I provide a C# DLL called managed.dll which is COM visible. I provide as well the TLB file called managed.tlb.
  • a company B is using my managed.dll in a C++ EXE called unmanaged.exe.
  • a customer C has to get the managed.dll from my company A and the unmanaged.exe from company B. The reason for that is that company B is not allowed to redistribute the managed.dll from company A.

Now let's assume I add a method or property to one of my classes in my managed.dll. Then the unmanaged.exe from company B is broken. Company B has to recompile it with the newer tlb-file.

How can I avoid that company B has to recompile their unmanaged.exe when I add something to my managed.dll?

The reason why I'm asking is

  • I've no control when company B is recompiling or releasing their unmanaged.exe. Even if I provide my managed.dll to company B every time I've added something.
  • I've no control which versions of the managed.dll and unmanaged.exe the customer C is using.
  • company B would like to claim that their unmanaged.exe V1.0 is working with my managed.dll V1.0 or newer.

How can we achieve that?

The source code of my managed.dll looks like that:

[Guid("852e5991-ddcc-56dd-8e13-90dcaf11ebe5")]
[ComVisible(true)]
public interface ITestA
{
    string DummyString();
    int DummyInt();
}

[Guid("41916928-6bea-43de-bedb-318df340e7b8")]
[ComVisible(true)]
[ComDefaultInterface(typeof(ITestA))]
public class TestA : ITestA
{
    public string DummyString() { return "Dummy"; }
    public int DummyInt() { return 123; }
}

The tlb-file is generated with RegAsm.exe managed.dll /tlb /codebase.

The source code of the unmanaged.exe looks like that:

#include "stdafx.h"
#import "managed.tlb"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
    HRESULT hr = CoInitialize(NULL); // Init COM
    IClassAPtr pClassA(__uuidof(ClassA));
    // and so on ...
}

Regards Wollmich

7
  • 2
    Changing the binary layout (signatures, add/remove methods, etc.) of a published IUnknown interface is kinda forbidden. You must provide new interfaces (like ITestA2, ITestA3, etc.). Or you could propose an Automation (late binding/IDispatch) interface instead of relying on IUnknown derivates. But it's somehow more work on the C++ side. Commented May 15, 2017 at 9:11
  • @Simon Mourier: Is this described somewhere in MSDN? Or do you have a reference which says that I've to provide a new Interface (ITestA2) if I want to add new methods? Commented May 15, 2017 at 12:13
  • @Wollmich: It's one of those "It's so obvious we don't need to state it" things. Each interface has a Globally Unique ID (GUID). Obviously, that only makes sense if the GUID identifies something that's indeed unique. Since you define two interfaces (old and new), you better have two ID's. Commented May 15, 2017 at 12:23
  • 1
    COM interfaces are immutable. This is explicitly documented here for example, but it's fairly logical: msdn.microsoft.com/en-us/library/windows/desktop/ms688484.aspx Commented May 15, 2017 at 12:36
  • @Simon Mourier: Thanks for the link. I can understand that an instance of an interface implementation is actually a pointer to an array of pointers to methods. But then I should be able to add new methods at the end of the ITestA interface. I've tested that and it's working as long I'm adding new methods at the end and not in the middle. But I guess that is still kinda forbidden, right? Commented May 15, 2017 at 12:56

2 Answers 2

2

There's a reason Microsoft defined IHTMLEventObj6. That's the 5th incremental update of IHTMLEventObj. You'll need to do the same: ITestA2 will need to inherit ITestA and add extra methods.

Sign up to request clarification or add additional context in comments.

Comments

0

It turned out that I've to provide new interfaces (like ITestA2, ITestA3, etc.) if I want to add new methods or properties to my managed.dll.

So the source code of the managed.dll could be extended like that:

[Guid("5ff6c41a-6e4c-4d96-8e5e-72a560715b56")]
[ComVisible(true)]
public interface ITestA2
{
    string DummyString();
    int DummyInt();
    bool DummyBool(); // new method
}

[Guid("d5b8f4b5-d33f-4e7d-866c-ef0844216a3a")]
[ComVisible(true)]
[ComDefaultInterface(typeof(ITestA2))]
public class TestA2 : TestA, ITestA2
{
    public bool DummyBool() { return true; }
}

Remarks for .NET

In COM interfaces can inherit from one another. However the .NET implementation that exposes the .NET interface to COM does not support inheritance. Therefore you must replicate any interface members in a base interface to the derived interface.

see COM Interop: Base class properties not exposed to COM.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.