Building COM Objects in C#
|Download : Source Code|
The topics covered in this article are
For the sake of simplycity and ease of use for the developers , testing this code , I have used the Northwind database built into with the default installation of SQLSERVER database.
|Part I : Creating a simple COM Object in C#.|
COM Objects are of the type ClassLibrary. The COM Object generates a DLL file. To create a simple COM object from the VS Development Environment. Select ….
Create a project name called Database_COMObject.
Remember : Exposing the VC# objects to the COM world requires the following …
Other public members in the class that are not declared in these interfaces will not be visible to COM, but they will be visible to other .NET Framework objects. To expose properties and methods to COM, you must declare them on the class interface and mark them with a DispId attribute, and implement them in the class. The order the members are declared in the interface is the order used for the COM vtable. To expose events from your class, you must declare them on the events interface and mark them with a DispId attribute. The class should not implement this interface. The class implements the class interface (it can implement more than one interface, but the first implementation will be the default class interface). Implement the methods and properties exposed to COM here. They must be marked public and must match the declarations in the class interface. Also, declare the events raised by the class here. They must be marked public and must match the declarations in the events interface.
Every Interface needs a GUID property set before the interface name. To generate the unique Guid , use the guidgen.exe utility and select the Registry Format.
Here is how the interface class looks like …
|For COM events ..|
// // Events interface Database_COMObjectEvents
|For the actual class decleration|
Note the following property set before the class
The ClassInterfaceType.None indicates ..
Indicates that no class interface is generated for the class. If no interfaces are implemented explicitly, the class will only provide late bound access through IDispatch. Users are expected to expose functionality through interfaces that are explicitly implemented by the class. This is the recommended setting for ClassInterfaceAttribute.
Here is the complete COM Object source ..
using System.Windows.Forms ;
// Events interface Database_COMObjectEvents
public void Init(string userid , string password)
public bool ExecuteSelectCommand(string selCommand)
SqlCommand myCommand = new SqlCommand(selCommand);
public bool NextRow()
public string GetColumnData(int pos)
public void ExecuteNonSelectCommand(string insCommand)
Before you build the COM object we have to Register the object for COM Interop. To do this right click the project name in the Solution Explorer. Click Properties. Click Configuration ->Build. Expand the output section. Set the Register for COM Interop to true.
Indicates that your managed application will expose a COM object (a COM-callable wrapper) that allows a COM object to interact with your managed application.
In order for the COM object to be exposed, your class library assembly must also have a strong name. To create a strong name use the utility SN.EXE.
sn -k Database_COM_Key.snk
Open the AssemblyInfo.cs and modify the line
Build the Object. The build also results into a type library that can be imported into your managed or unmanaged code.
|Part II : Creating a Client using Visual C++ to access this COM Object.|
I have tested the COM object with the VC++ 6.0 and VC++ .NET environment.
Create a simple project using the VC++ development environment.
Import the type library using the #import directive.
Create a Smart Pointer to the Interface.Execute the exposed functions from the interface. Make sure to add the CoInitialize() call when the application loads.
|This code executes a SQL Command against the Customers table and returns the customer information for a given customer ID|
| char cmd;
sprintf(cmd , "SELECT COMPANYNAME , CONTACTNAME ,
CONTACTTITLE , ADDRESS FROM CUSTOMERS WHERE CUSTOMERID = '%s'" , m_id );
const char *p ;
bool ret = db_com_ptr->ExecuteSelectCommand(cmd);
if ( ! db_com_ptr->NextRow() ) return ;
_bstr_t mData = db_com_ptr->GetColumnData(3);