如何实现在WINDOWS系统下两个进程的通讯问题。

进程之间通讯的几种方法:
在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);  
} 

注意这里发送消息的函数:public static void SendMessage(string destProcessName, int msgID, string strMsg),只能发送一个msgID和一个strMsg, 接收方只接收了strMsg

    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;  
        }  
        
    /**//// 
    /// 本类封装了一些进程间通讯的细节
    /// 
    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        // 第二个消息参数
        );  

    /**//// 
    /// 发送消息,只能传递一个自定义的消息ID和消息字符串,想传一个结构,但没成功
    /// 
    /// 目标进程名称,如果有多个,则给每个都发送
    /// 自定义数据,可以通过这个来决定如何解析下面的strMsg
    /// 传递的消息,是一个字符串
    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);  
            }
        }
    }

    /**//// 
    /// 接收消息,得到消息字符串
    /// 
    /// System.Windows.Forms.Message m
    /// 接收到的消息字符串
    public static string ReceiveMessage(ref  System.Windows.Forms.Message  m)
    {
        CopyDataStruct  cds = (CopyDataStruct) m.GetLParam(typeof(CopyDataStruct));  
        return cds.lpData;
    }

}  

}

你可能感兴趣的:(如何实现在WINDOWS系统下两个进程的通讯问题。)