On .NET/COM Interoperability

compiled by Elena Smirnova

I. Deploying a .NET Application for COM Access

  1. Create a .NET assembly containing a class that will be called by a COM client.
    Keep in mind a special requirement for the .NET code structure:

    • the .NET code should export a signed interface
      Guid("2D570F11-4BD8-40e7-BF14-38772063AAF0")]
      [InterfaceType(ComInterfaceType.InterfaceIsDual)]
      public interface INETCode
      {
      // exposed properties and methods
      }

    • In the .NET class, the INETCode interface should be the first interface implemented in the class declaration:

      [Guid("478176F4-5105-435c-8EBC-D4CB90B7B1C7")]
      [ClassInterface(ClassInterfaceType.None)]
      [ProgId("<Namespace>.NETCode")]
      public class NETCode : System.Windows.Forms.UserControl, INETCode
      {
      // implementation exposed methods for properties getter/setters.
      }

  2. Create a key pair and use it to sign the assembly to make the assembly globally available.
    To make it easier to work with the assembly one can add a title and description.
    To sign the assembly, one can run the sn utility and add the name of the key file by hand,
    or you can generate a strong name using the Visual Studio .NET user interface
    by edditing the <assembly-nameInfo>.vb file.

    The Assembly.cs file then will contain a line like this one
    . . .
    [assembly: AssemblyKeyFile(@"KeyFile.snk")]
    [assembly: AssemblyKeyName("...")]
    //
    // The assembly-level GuidAttribute becomes the typelib ID.
    //
    [assembly: Guid("9D414AA8-B6FC-4324-8B86-FCF207A82E3D")]

    This Guid will later be used to call this assembly from a COM code.

  3. Create a type library for the assembly (.tbl) with tblexp:
    tlbexp <assembly-name>.dll /out:<table-name>.tlb

  4. Register the type library (also creates the library itself).
    For it use the Assembly Registration Tool regasm from the .NET Framework SDK:
    regasm /tlb:<table-name>.tlb <assembly-name>.dll

  5. Install the .NET assembly into the Global Assembly Cache (GAC)
    so that it will be available as a shared assembly. To install an assembly into the GAC, use the gacutil tool:
    gacutil /i<assembly-name>.dll

II. Calling a .NET assembly from within Visual C++ COM code

  1. In order to call the .NET assembly from a COM code (C++ or VB), we have to refer to that assembly by its GUID: #import "libid:9D414AA8-B6FC-4324-8B86-FCF207A82E3D" raw_interfaces_only named_guids

  2. We'll need to include namespace in the COM code:
    using namespace NETCode;

  3. Now, to use the assembly properties and methods we'll need to define a pointer to its interface:
    static CComPtr<INETCode> d_netObject = NULL;

  4. To access an exposed property method just use it in a usial way
    if (d_netObject != NULL)
    {
       hr = d_netObject->get_Property1(&variable);
       if (SUCCEEDED(hr))
       {
        // do something with this variable
       }
    }
    else
       return NULL;