Thursday, September 5, 2013

C# COM Interop And Events

By using COM Interop, it is possible to expose the events from your managed component to COM environment. I've used the sample in Exposing Com Events for making my own implementation as below.

This example shows how to create a project named MyCom.COM to allow COM Interop for MyCom.dll with Events:
  • MyCom is the original .Net managed assembly which consist of:
    • a public property SerialNo;
    • a method ReadData();
    • two events Progress and Error.
  • MyComHelper is a wrapper class for the original MyCom functions and events.
  • Interface classes IMyComHelper and IMyComHelperEvents are required by MyComHelper.

Steps to create:

1. In your project, add reference to System.EnterpriseServices.dll.

2. Add a class named as MyComHelper. Implementations of MyComHelper class and interfaces:
using System.Runtime.InteropServices;
using System.EnterpriseServices;

namespace MyCom.COM
{
    #region Interfaces

    #region IMyComHelper

    [ComVisible(true)]                                          // Exposed.
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]      // Our managed interface will be IDispatch.
    public interface IMyComHelper
    {
        string SerialNo { get; set; }
        bool ReadData();
    }

    #endregion

    #region IMyComHelperEvents

    [ComVisible(true)]                                          // Exposed.
    [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]      // Our managed interface will be IDispatch.
    public interface IMyComHelperEvents
    {
        void Progress(string data, decimal percent);
        void Error(string description, string source);
    }

    #endregion

    #endregion

    /// <summary>
    /// A COM wrapper class for the MyCom functions and events.
    /// </summary>
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [ComSourceInterfaces(typeof(IMyComHelperEvents))]                       // Our event source is IMyComHelperEvents interface.
    [ProgId("MyCom_COM.MyComHelper")]
    public class MyComHelper : ServicedComponent, IMyComHelper
    {
        #region Declare

        MyCom _myCom = new MyCom();                                         // The MyCom class from MyCom.dll.

        #region Declare Events

        [ComVisible(false)]
        public delegate void ProgressDel(string data, decimal percent);     // No need to expose this delegate.
        public event ProgressDel Progress;

        [ComVisible(false)]
        public delegate void ErrorDel(string description, string source);
        public event ErrorDel Error;

        #endregion

        #region Declare Properties

        public string SerialNo
        {
            get { return _myCom.SerialNo; }
            set { _myCom.SerialNo = value; }
        }

        #endregion

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the MyComHelper object.
        /// </summary>
        public MyComHelper()
        {
            _myCom.Progress += new MyCom.ProgressEventHandler(_myCom_Progress);
            _myCom.Error    += new MyCom.ErrorEventHandler(_myCom_Error);
        }

        #endregion

        #region Methods

        public bool ReadData()
        {
            return _myCom.ReadData();   // In this example, data is returned in the Progress event.
        }

        #endregion

        #region Events

        void _myCom_Progress(string data, decimal percent)
        {
            Progress(data, percent);
        }

        void _myCom_Error(object sender, MyCom.ErrorEventArgs e)
        {
            Error(e.Description, e.Source);
        }

        #endregion
    }
}
3. In the project Properties > Application > Assembly Information > Make assembly COM-Visible > Check. Build the project.

4. Register the assembly using RegAsm:
  • Copy MyCom.COM.dll and MyCom.dll (and any other local assemblies) to a folder.
  • Run in VS command prompt: regasm [yourpath]\MyCom.COM.dll /tlb /codebase

5. Now you can add reference to MyCom.COM.dll from your unmanaged code, and will be able to access it's events.


Additional Resources:
Regasm COM Interop Assembly With .Net Installer Project


If you find this post helpful, would you buy me a coffee?


No comments:

Post a Comment