您的位置:首页 > 编程语言 > C#

关于C#中实现两个应用程序消息通讯的问题

2017-06-13 12:46 555 查看
  最近项目中需要在两个应用程序之间通讯,这里的两个程序是在一台机器上,看了csdn上的一篇文章如何在C#用WM_COPYDATA消息来实现两个进程之间传递数据》,原理是讲清楚了,但使起来很不爽,决定自己封装一下,满足项目需要就行。

  注意这里发送消息的函数:public static void SendMessage(string destProcessName, int msgID, string strMsg),只能发送一个msgID和一个strMsg, 接收方只接收了strMsg,我的项目中已经够用了,你如果需要读msgID,还需要改一下。客户端代码请参考csdn上的原文自己写吧。


/*


 进程之间通讯的几种方法: 


 在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯。常用的方法有  


 (1)使用内存映射文件  


 (2)通过共享内存DLL共享内存  


 (3)使用SendMessage向另一进程发送WM_COPYDATA消息  


 


 比起前两种的复杂实现来,WM_COPYDATA消息无疑是一种经济实惠的一种方法.  


 WM_COPYDATA消息的主要目的是允许在进程间传递只读数据。Windows在通过WM_COPYDATA消息传递期间,不提供继承同步方式。


 SDK文档推荐用户使用SendMessage函数,接受方在数据拷贝完成前不返回,这样发送方就不可能删除和修改数据:  


 


 这个函数的原型及其要用到的结构如下:  


 SendMessage(hwnd, WM_COPYDATA, wParam, lParam);    


 其中:


 WM_COPYDATA对应的十六进制数为0x004A  


 wParam设置为包含数据的窗口的句柄。


 lParam指向一个COPYDATASTRUCT的结构:  


 typedef  struct  tagCOPYDATASTRUCT


 {  


             DWORD  dwData;  //用户定义数据  


             DWORD  cbData;  //数据大小  


             PVOID  lpData;  //指向数据的指针  


 } COPYDATASTRUCT;  


 该结构用来定义用户数据。  


 


 具体过程如下:  


 首先,在发送方,用FindWindow找到接受方的句柄,然后向接受方发送WM_COPYDATA消息。


 接受方在DefWndProc事件中处理这条消息。由于中文编码是两个字节, 所以传递中文时候字节长度要搞清楚。  


 protected  override  void  DefWndProc(ref  System.Windows.Forms.Message  m)  {  


     switch(m.Msg)  {  


         case  WinMessageUtil.WM_COPYDATA:  


               string str = WinMessageUtil.ReceiveMessage(ref m);


               break;


         default:  


               break;  


     }


     base.DefWndProc(ref  m);  


 }  


*/




using System;


using  System.Runtime.InteropServices;  


using System.Diagnostics;




namespace Speeding.Util


{




    //WM_COPYDATA消息所要求的数据结构


    public  struct  CopyDataStruct  


    {  


        public  IntPtr  dwData;  


        public  int  cbData;  




        [MarshalAs(UnmanagedType.LPStr)]  


        public  string  lpData;  


    }  


    


    /// <summary>


    /// 本类封装了一些进程间通讯的细节


    /// </summary>


    public class WinMessageUtil


    {


        public const  int  WM_COPYDATA  =  0x004A;  




        //通过窗口的标题来查找窗口的句柄


        [DllImport("User32.dll",EntryPoint="FindWindow")]  


        private  static  extern  int  FindWindow(string  lpClassName, string  lpWindowName);  




        //在DLL库中的发送消息函数


        [DllImport("User32.dll",EntryPoint="SendMessage")]  


        private  static  extern  int  SendMessage


            (  


            int  hWnd,                        // 目标窗口的句柄  


            int  Msg,                        // 在这里是WM_COPYDATA


            int  wParam,                    // 第一个消息参数


            ref  CopyDataStruct  lParam        // 第二个消息参数


            );  


 


        /// <summary>


        /// 发送消息,只能传递一个自定义的消息ID和消息字符串,想传一个结构,但没成功


        /// </summary>


        /// <param name="destProcessName">目标进程名称,如果有多个,则给每个都发送</param>


        /// <param name="msgID">自定义数据,可以通过这个来决定如何解析下面的strMsg</param>


        /// <param name="strMsg">传递的消息,是一个字符串</param>


        public static void SendMessage(string destProcessName, int msgID, string strMsg) 


        {


            if(strMsg == null) return;




            //按进程名称查找,同名称的进程可能有许多,所以返回的是一个数组


            Process []foundProcess = Process.GetProcessesByName(destProcessName);


            foreach(Process p in foundProcess) 


            {


                int toWindowHandler = p.MainWindowHandle.ToInt32();


                if(toWindowHandler  !=  0)  


                {  


                     CopyDataStruct  cds;  


                    cds.dwData  =  (IntPtr)  msgID;   //这里可以传入一些自定义的数据,但只能是4字节整数      


                    cds.lpData  =  strMsg;            //消息字符串


                    cds.cbData  =  System.Text.Encoding.Default.GetBytes(strMsg).Length + 1;  //注意,这里的长度是按字节来算的




                    //发送方的窗口的句柄, 由于本系统中的接收方不关心是该消息是从哪个窗口发出的,所以就直接填0了


                    int fromWindowHandler = 0;    


                    SendMessage(toWindowHandler,  WM_COPYDATA,  fromWindowHandler,  ref  cds);  


                }


            }


        }




        /// <summary>


        /// 接收消息,得到消息字符串


        /// </summary>


        /// <param name="m">System.Windows.Forms.Message m</param>


        /// <returns>接收到的消息字符串</returns>


        public static string ReceiveMessage(ref  System.Windows.Forms.Message  m)


        {


            CopyDataStruct  cds = (CopyDataStruct) m.GetLParam(typeof(CopyDataStruct));  


            return cds.lpData;


        }




    }  




    


}



转自 : http://www.cnblogs.com/speeding/archive/2004/10/24/56033.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: