Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turn a simple C# DLL into a COM interop component

How do I make a C# DLL into a COM interop DLL that can be consumed by a VB6 application?

like image 249
Elena Lawrence Avatar asked Aug 17 '11 12:08

Elena Lawrence


People also ask

What is Makefile in C?

Makefile is a set of commands (similar to terminal commands) with variable names and targets to create object file and to remove them. In a single make file we can create multiple targets to compile and to remove object, binary files. You can compile your project (program) any number of times by using Makefile.

What is turn in C?

What is Turn C-bet in Poker? « View All Poker Terms. A turn c-bet means betting on the turn after raising preflop and betting the flop. For example, if you raise on the Hijack and the button calls, and you bet again on the flop, you're making a continuation bet, or c-bet.

What is .2lf C?

2lf is used of long double it is a format specifier used in C language. . 2 is used for controlling the width of the decimal places.


2 Answers

This is the answer I wanted to find in StackOverflow but couldn't. It turns out to be fairly easy to turn a simple C# dll into a COM dll.

To create the C# dll

Create a solution with a C# class project. The class should have an interface for the properties/methods and an interface for the events. Assign GUID attributes to the class and interfaces as described in MSDN - Example COM Class (C# Programming Guide). Also see: MSDN - How to: Raise Events Handled by a COM Sink.

In Project Properties > Application tab > Assembly Information button > check "Make assembly COM-Visible". This makes all public methods in the class COM visible.

In Project Properties > Build tab > Set "Platform target" to x86.

That's all you need to do to create the DLL. To call the DLL, you need to register it.

Registering the DLL on your development machine

You can register the DLL one of these ways:

  • Check Project Properties > Build Tab > "Register for COM Interop". This will automatically register the DLL when you build it.
  • Manually register the DLL with RegAsm. This allows you to register the DLL in the directory of your choice, rather than in the build directory. This is the method I used.

    • Do not check Project Properties > Build Tab > "Register for COM Interop"
    • Copy the DLL to the directory where you want to register it
    • Open a command shell with administrator rights and type

      RegAsm.exe -tlb -codebase mydll.dll 

      RegAsm.exe can be found in "C:\Windows\Microsoft.NET\Framework\v2.0.50727", while "mydll.dll" is the name of your DLL; tlb means "create a type library"; codebase means "write the directory location to the Registry, assuming it is not being placed in the GAC".

      RegAsm will display a warning that the assembly should be strong-named. You can ignore it.

      At this point, you should be able to add a reference to the COM DLL in VB6, see it with Intellisense, and run it just like a regular COM DLL.

Installing the DLL with InstallShield

If you are using InstallShield to install the DLL along with the rest of your application, do the following.

In InstallShield, add a new Component to the Components list. Remember to associate the Component with a Feature. Set component property ".NET COM Interop" to Yes.

Add the .dll file to the Files section of the Component. Do not check the "Self-Register" property. Right-click on the .dll file and select "Set Key File".

Add the .tlb file to the Files section of the Component. Check the "Self-Register" property.

The correct version of the .Net Framework needs to exist on the target PC.

That's it.

like image 184
Kieren Johnstone Avatar answered Oct 09 '22 17:10

Kieren Johnstone


As en extension to @Kieren Johnstone's answer a practical code example on class modifications you need to do:

From:

public class ApiCaller  {      public DellAsset GetDellAsset(string serviceTag, string apiKey)     {      ....     } }  public class DellAsset {     public string CountryLookupCode { get; set; }     public string CustomerNumber { get; set; }     public bool IsDuplicate { get; set; }     public string ItemClassCode { get; set; }     public string LocalChannel { get; set; }     public string MachineDescription { get; set; }     public string OrderNumber { get; set; }     public string ParentServiceTag { get; set; }     public string ServiceTag { get; set; }     public string ShipDate { get; set; }  } 

To:

[Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83F")] [ComVisible(true)] public interface IComClassApiCaller {     IComClassDellAsset GetDellAsset(string serviceTag, string apiKey);  }  [Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA71"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] [ComVisible(true)] public interface IComClassApiCallerEvents { }  [Guid("0D53A3E8-E51A-49C7-944E-E72A2064F938"),     ClassInterface(ClassInterfaceType.None),     ComSourceInterfaces(typeof(IComClassApiCallerEvents))] [ComVisible(true)] [ProgId("ProgId.ApiCaller")] public class ApiCaller : IComClassApiCaller {      public IComClassDellAsset GetDellAsset(string serviceTag, string apiKey)     {         .....     } }   [Guid("EAA4976A-45C3-4BC5-BC0B-E474F4C3C83E")] [ComVisible(true)] public interface IComClassDellAsset {      string CountryLookupCode { get; set; }      string CustomerNumber { get; set; }      bool IsDuplicate { get; set; }      string ItemClassCode { get; set; }      string LocalChannel { get; set; }      string MachineDescription { get; set; }      string OrderNumber { get; set; }      string ParentServiceTag { get; set; }      string ServiceTag { get; set; }      string ShipDate { get; set; }  }  [Guid("7BD20046-DF8C-44A6-8F6B-687FAA26FA70"), InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] [ComVisible(true)] public interface IComClassDellAssetEvents { }  [Guid("0D53A3E8-E51A-49C7-944E-E72A2064F937"),     ClassInterface(ClassInterfaceType.None),     ComSourceInterfaces(typeof(IComClassDellAssetEvents))] [ComVisible(true)] [ProgId("ProgId.DellAsset")] public class DellAsset : IComClassDellAsset {     public string CountryLookupCode { get; set; }     public string CustomerNumber { get; set; }     public bool IsDuplicate { get; set; }     public string ItemClassCode { get; set; }     public string LocalChannel { get; set; }     public string MachineDescription { get; set; }     public string OrderNumber { get; set; }     public string ParentServiceTag { get; set; }     public string ServiceTag { get; set; }     public string ShipDate { get; set; }  } 

Hope this saves you some time

like image 24
Matas Vaitkevicius Avatar answered Oct 09 '22 17:10

Matas Vaitkevicius