C#中实现两个程序的通信

来源:互联网 发布:程序员笔试编程题 编辑:程序博客网 时间:2024/06/05 22:44

 在Windows下的两个进程之间通信通常有命名管道、消息队列、共享内存等实现方式,这篇文章要讲解的是使用Windows的API来实现简单的进程间通信。对于接收消息,只需要重写DefWndProc函数即可,对于发送消息,写一个发送消息MsgHandler来实现。

首先是MsgHandler类

using System;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;


namespace CommunicationTest
{
    /// <summary>  
    /// 发送消息处理程序类
    /// 调用该方法“SendMessageToTargetWindow”发送  
    /// </summary>  
    class MsgHandler
    {
        /// <summary>  
        /// 系统定义的消息
        /// </summary>  
        private const int WM_COPYDATA = 0x004A;


        /// <summary>  
        /// 用户己定义消息
        /// </summary>  
        private const int WM_DATA_TRANSFER = 0x0437;


        // 使用Windows API的FindWindow方法
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern int FindWindow(string lpClassName, string lpWindowName);


        //使用Windows API的IsWindow方法
        [DllImport("User32.dll", EntryPoint = "IsWindow")]
        private static extern bool IsWindow(int hWnd);


        // 使用Windows API的SendMessage方法
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
            int hWnd,                 
            int Msg,                   
            int wParam,                
            ref COPYDATASTRUCT lParam   
        );


        // 使用Windows API的SendMessage方法
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(
            int hWnd,                   
            int Msg,                   
            int wParam,                
            string lParam               
        );


        /// <summary>  
        /// CopyDataStruct  
        /// </summary>  
        private struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;
        }


        /// <summary>  
        /// 向目标窗口发送消息
        /// </summary>  
        /// <param name="wndName">查找目标窗体名称</param>  
        /// <param name="msg">要发送的消息,字符串</param>  
        /// <returns>返回的数据是否成功或则失败</returns>  
        public static bool SendMessageToTargetWindow(string wndName, string msg)
        {
            Debug.WriteLine(string.Format("SendMessageToTargetWindow: 向目标窗口发送消息 {0}: {1}", wndName, msg));


            int iHWnd = FindWindow(null, wndName);
            if (iHWnd == 0)
            {
               string strError = string.Format("SendMessageToTargetWindow: 没有发现{0}窗体!", wndName);
                MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Debug.WriteLine(strError);
                return false;
            }
            else
            {
                byte[] bytData = null;
                bytData = Encoding.Default.GetBytes(msg);


                COPYDATASTRUCT cdsBuffer;
                cdsBuffer.dwData = (IntPtr)100;
                cdsBuffer.cbData = bytData.Length;
                cdsBuffer.lpData = Marshal.AllocHGlobal(bytData.Length);
                Marshal.Copy(bytData, 0, cdsBuffer.lpData, bytData.Length);


                // 使用系统定义的消息wmcopydata来发送消息。 
                int iReturn = SendMessage(iHWnd, WM_COPYDATA, 0, ref cdsBuffer);
                if (iReturn < 0)
                {
                    string strError = string.Format("SendMessageToTargetWindow: 没有发现{0}窗体!", wndName);
                    MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Debug.WriteLine(strError);
                    return false;
                }
                return true;
            }
        }


        /// <summary>  
        /// 向目标窗口发送消息
        /// </summary>  
        /// <param name="wndName">查找目标窗体名称</param>  
        /// <param name="wParam">first parameter, integer</param>  
        /// <param name="lParam">second parameter, string</param>  
        /// <returns>数据发送成或者失败</returns>  
        public static bool SendMessageToTargetWindow(string wndName, int wParam, string lParam)
        {
            Debug.WriteLine(string.Format("SendMessageToTargetWindow: Send message to target window {0}: wParam:{1}, lParam:{2}", wndName, wParam, lParam));
            int iHWnd = FindWindow(null, wndName);
            if (iHWnd == 0)
            {
                string strError = string.Format("SendMessageToTargetWindow: The target window [{0}] was not found!", wndName);
                MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                Debug.WriteLine(strError);
                return false;
            }
            else
            {
                //使用定义的消息wmdatatransfer来发送消息。
                int iReturn = SendMessage(iHWnd, WM_DATA_TRANSFER, wParam, lParam);
                if (iReturn < 0)
                {
                    string strError = string.Format("SendMessageToTargetWindow: Send message to the target window [{0}] failed!", wndName);
                    MessageBox.Show(strError, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    Debug.WriteLine(strError);
                    return false;
                }


                return true;
            }
        }
    }
}

然后是数据接收窗体

using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;


namespace CommunicationTest
{
    public partial class First : Form
    {
        /// <summary>  
        ///系统定义的消息
        /// </summary>  
        private const int WM_COPYDATA = 0x004A;


        /// <summary>  
        /// User defined message  
        /// </summary>  
        private const int WM_DATA_TRANSFER = 0x0437;


        /// <summary>  
        /// CopyDataStruct  
        /// </summary>  
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;
        }
        public First()
        {
            InitializeComponent();
        }


        /// <summary>  
        ///覆盖DefWndProc函数,以便通过它接收消息。 
        /// </summary>  
        /// <param name="m">message</param>  
        protected override void DefWndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                // 这里,我们使用wmcopydata消息来接收COPYDATASTRUCT
                case WM_COPYDATA:
                    COPYDATASTRUCT cds = new COPYDATASTRUCT();
                    cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
                    byte[] bytData = new byte[cds.cbData];
                    Marshal.Copy(cds.lpData, bytData, 0, bytData.Length);
                    this.ProcessIncomingData(bytData);
                    break;


                // 在这里,我们使用我们定义的消息wmdatatransfer来接收 
                // 普通数据,例如整数,字符串。
                // 我们尝试使用我们定义的消息来接收COPYDATASTRUCT,  
                // 但它没工作! !它告诉我们,我们试图进入受保护的   
                //,通常意味着其他记录被打破了。
                case WM_DATA_TRANSFER:
                    int iWParam = (int)m.WParam;
                    string sLParam = m.LParam.ToString();
                    this.ProcessIncomingData(iWParam, sLParam);
                    break;


                default:
                    base.DefWndProc(ref m);
                    break;
            }
        }


        /// <summary>  
        /// 处理传入的数据 
        /// </summary>  
        /// <param name="data">输入数据</param>  
        private void ProcessIncomingData(byte[] bytesData)
        {
            string strRevMsg = "Receive message: " + Encoding.Default.GetString(bytesData);
            textBox7.Text = Encoding.Default.GetString(bytesData);
            //lstReceivedMsg.Items.Add(strRevMsg);
        }


        /// <summary>  
        /// 处理传入的数据  
        /// </summary>  
        /// <param name="iWParam">一个整数</param>  
        /// <param name="sLParam">一个字符串参数</param>  
        private void ProcessIncomingData(int iWParam, string sLParam)
        {
            StringBuilder strBuilder = new StringBuilder();
            strBuilder.Append("wParam: ");
            strBuilder.Append(iWParam.ToString());
            strBuilder.Append(", lParam: ");
            strBuilder.Append(sLParam);


           //lstReceivedMsg.Items.Add(strBuilder.ToString());
        }


        private void FrmTest_Load(object sender, EventArgs e)
        {
            this.Text = "First Test Form";
            this.txtCurrentWndName.Text = "First Test Form";
            this.txtTargetWndName.Text = "Second Test Form";
        }


        private void txtCurrentWndName_TextChanged(object sender, EventArgs e)
        {
            this.Text = txtCurrentWndName.Text;
        }


        /// <summary>  
        /// 使用系统定义的消息wmcopydata向目标窗口发送消息
        /// </summary>  
        private void btnSend1_Click_1(object sender, EventArgs e)
        {
            string strWndName = this.txtTargetWndName.Text;
            //检查目标窗口的名称为空/空
            if (string.IsNullOrEmpty(strWndName))
            {
                MessageBox.Show("目标窗口名不能为空或空", "Information", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }


            string strMsg = this.txtSendingMsg.Text;
            // 检查发送消息是空的还是空的 
            if (string.IsNullOrEmpty(strMsg))
            {
                MessageBox.Show("发送消息必须不是空的或空的!", "Information", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                return;
            }
            //向目标窗口发送消息
            bool bReturn = MsgHandler.SendMessageToTargetWindow(strWndName, strMsg);
        }
        /// <summary>
        /// 初始化页面
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
        
            this.Text = "First Test Form";
            this.txtCurrentWndName.Text = "First Test Form";
            this.txtTargetWndName.Text = "Second Test Form";
        }


        private void txtCurrentWndName_TextChanged_1(object sender, EventArgs e)
        {
            this.Text = txtCurrentWndName.Text;
        }


    }
}

接收数据是只要重写DefWndProc函数


原创粉丝点击