Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Bringing DCOM remoting functionality to Windows CE and .NET CF2.0

, 17 Apr 2006 CPOL
This article shows how to use DCOM on Windows CE 5.0. We will add full DCOM rich error information, and implement a DCOM interface between a Windows XP .NET 2.0 client and Windows CE DCOM server. With this code, it is possible to code .NET remoting alike functionality through DCOM interop.
////////////////////////////////////////////////////////////////////
//
//  Copyright (C) 2006 Werner Willemsens
//
////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace ControlRoom
{
    public partial class Form1 : Form
    {
        public StarGateLib.GateClass gateclass = null;
        public StarGateLib.IGate igate = null;
        public StarGateLib._IGateEvents_Event igate_event = null;

        public Form1()
        {
            InitializeComponent();

            // Do not allow gate to be dialed until created
            this.btnDialGate.Enabled = false;
            this.btnCloseGate.Enabled = false;
            this.btnDestroy.Enabled = false;

            // Reset chevron count
            this.textBox1.Text = "0";
            // No wormhole yet established
            this.textBox2.Text = "";
        }

        private void btnCreate_Click(object sender, EventArgs e)
        {
            try
            {
                // Create the gate
                this.gateclass = new StarGateLib.GateClass();

                // Ask for IGate itf (QueryInterface)
                this.igate = (StarGateLib.IGate)gateclass;

                // Ask for the IGate Event itf (QueryInterface)
                this.igate_event = (StarGateLib._IGateEvents_Event)gateclass;
                // Add eventhandler
                this.igate_event.Opened += new StarGateLib._IGateEvents_OpenedEventHandler(igate_event_Opened);

                // Allow gate to be dialed
                this.btnDialGate.Enabled = true;
                this.btnCloseGate.Enabled = true;
                this.btnDestroy.Enabled = true;
            }
            catch (System.Runtime.InteropServices.COMException err)
            {
                // If COM rich error info is properly send along, we should be able to see 
                // the error description
                MessageBox.Show(ComError.ComError.GetRichErrorInfo(err).Message);
                this.btnDialGate.Enabled = false;
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }

        private delegate void igate_event_OpenedCallback(string destination);
        private void igate_event_Opened(object Destination)
        {
            // The igate_event_Opened method will be called from the
            // COM runtime in ANOTHER thread
            // As it is not allowed to update a textbox object from another
            // thread it was created on, we need to invoke a separate callback
            // method on the original thread

            // Next line will fail (even crash VS2005)
            //          textBox2.Text = destination;
            string s = Convert.ToString(Destination);
            System.Diagnostics.Debug.WriteLine("Level1:" + s);

            // Instead invoke update to callback on original thread
            this.textBox2.Invoke(new igate_event_OpenedCallback(this.Update_igate_event_Opened),
                                 new object[] { s });
        }

        private void Update_igate_event_Opened(string destination)
        {
            string s = Convert.ToString(destination);
            System.Diagnostics.Debug.WriteLine("Level2:" + s);
            this.textBox2.Text = s;
        }

        private void btnDialGate_Click(object sender, EventArgs e)
        {
            // The igate.Dial() method will fire back immediately at us.
            // COM event notification is synchronous, ie it waits until the client
            // has finished processing the event.
            // As the COM server event Opened() will arrive on our main thread, it can not be processed
            // as long as the receiving thread (=main thread) is busy doing something,
            // but the main thread is busy doing igate.Dial().
            // Result = a deadlock, oh yes.
            // Therefore we can do only 2 things, either call the igate.Dial() method from another thread
            // or fire the COM event from a seperate thread. 
            // I have chosen the latter option in this example because the COM event workerthread 
            // is the nicest solution:-) (the client is not bothered with this problem)
            try
            {
                if (this.igate != null)
                {
                    // Dial
                    this.igate.DialGate(Convert.ToInt32(this.textBox1.Text));
                    // Auto increase chevron count
                    this.textBox1.Text = Convert.ToString(Convert.ToInt32(this.textBox1.Text) + 1);
                }
            }
            catch (System.Runtime.InteropServices.COMException err)
            {
                // If COM rich error info is properly send along, we should be able to see 
                // the error description
                MessageBox.Show(ComError.ComError.GetRichErrorInfo(err).Message);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }

        private void btnCloseGate_Click(object sender, EventArgs e)
        {
            try
            {
                this.igate.CloseGate();
                this.textBox1.Text = Convert.ToString(0);
            }
            catch (System.Runtime.InteropServices.COMException err)
            {
                // If COM rich error info is properly send along, we should be able to see 
                // the error description
                MessageBox.Show(ComError.ComError.GetRichErrorInfo(err).Message);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
       }

        private void btnDestroy_Click(object sender, EventArgs e)
        {
            Destroy();
        }

        private void Destroy()
        {
            try
            {
                if (this.igate != null)  // Already destroyed??
                {
                    this.igate_event.Opened -= new StarGateLib._IGateEvents_OpenedEventHandler(igate_event_Opened);
                    this.igate_event = null;
                    this.igate = null;

                    this.btnDialGate.Enabled = false;
                    this.btnCloseGate.Enabled = false;
                    this.btnDestroy.Enabled = false;
                }
            }
            catch (System.Runtime.InteropServices.COMException err)
            {
                // If COM rich error info is properly send along, we should be able to see 
                // the error description
                MessageBox.Show(ComError.ComError.GetRichErrorInfo(err).Message);
            }
            catch (Exception err)
            {
                MessageBox.Show(err.Message);
            }
        }

        private void Form1_Closing(object sender, CancelEventArgs e)
        {
            Destroy();
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Werner Willemsens
Team Leader
Belgium Belgium
No Biography provided

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.141216.1 | Last Updated 17 Apr 2006
Article Copyright 2006 by Werner Willemsens
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid