Search code examples
c#visual-studio-2017cominteropcom-interop

VS2017 Reference Manager does not show Managed COM components on the COM tab


I have a number of C# Assemblies which have been built and registered as COM components. They work perfectly fine when invoked from unmanaged code (Fujitsu NetCOBOL for Windows) and I also have no difficulty when invoking COBOL COM components from C#. The unmanaged COM component appears in the VS 2017 Reference Manager COM tab, VS 2017 generates the Interop and it is all excellent.

But if I try to use one of the managed COM components with managed code (a C# .exe), the VS 2017 Reference Manager doesn't show an entry for the .DLL. Instead, it presents the DESCRIPTION of the component instead of the NAME, and it is pointing to the .TLB which was generated when I built the original component. If I select that reference, this happens:

enter image description here

If I go and Browse for the .DLL the reference is added OK, but it forces me to "Copy Local" and I get a copy of the .DLL deployed with my executable.

Screenshot of referenced component properties

If I try and make it false, and embed the types, it fails to build and I get a message about some obscure attributes not being set...

If I build it as shown, it deploys and works perfectly, but I am adding a copy of the COM component .dll to every executable I deploy. That kind of defeats the object of COM components where one copy of the code is shared between users. I used COM for years with unmanaged code and never had any problems. Is a different understanding required for use with managed code?

I have spent a number of hours reading the docs on COM and interOP (although InterOP is not applicable here I think, as both the client and the server are managed code.)

Is there something I need to set when I build the component? (I use "Make COM Visible" and it certainly seems to register it OK. However, I noticed that if I unregister it with Regasm it does not clear the registry entries...

Is there a VS 2017 setting I am missing or something in the build? Any help would be gratefully received.

Pete.


Solution

  • After some intensive reading and experimentation I finally solved the problem.

    SUMMARY: To be able to used managed COM components in the same way as we used unmanaged ones (one copy, registered and shared by all users), you SHOULD NOT try and add the .DLL as a reference to your project. Instead, you late bind the component and use reflection to implement its interfaces, methods, and properties.

    This means doing the following:

    1. Getting an instance of the component dynamically at run time.

    2. using reflection on that instance to access properties and methods in the normal way.

    DETAILS and CODE SAMPLES (to hopefully save someone else from having to do the background I did...):

    First thing: DON'T add a reference to the .DLL to your Project.

    I set up some global variables as follows:

    code sample 1

    Now I needed to consider what actions I wanted. I wanted a general solution so that I could use it on ANY COM reference and what I'm posting here is close, but things like specific error messages have not been replaced with variables yet.

    The COM object supports Getting and Setting Properties and invoking Methods. I also need to be able to instantiate it easily.

    The methods I have written here return a dynamic value in retVal.

    They have been tested and all work very well, so I can continue to use the managed COM components just as I did the unmanaged ones, by simply adding the code samples here to any project that deals with them, and invoking these methods to deal with a given managed COM component. I do not claim to be an expert in C# and I'm sure that more experienced people will find better ways to code than I have, but it does work and that is always a good thing... :-)

    I was a little concerned that using reflection might slow everything down, but in practice it is no "slower" than late binding any COM object is.

    Here are the methods: (Sorry for code misalignment; I'm new to this...)

    The method to instantiate the COM object. The example uses something called "RAVDesktop.dll"

    code sample 2 code sample 3

    Now the "Action" methods for properties and methods in the COM object...

    code sample 4 code sample 5 code sample 6

    Here's an example of instantiating the component, then setting a Property in it called "WebServiceURL", and, if the setting succeeded, retrieving it so it can be checked:

    code sample 7

    Grateful thanks to all who contributed. Stack Overflow rocks!

    Pete.