日期:2014-05-17  浏览次数:20757 次

在.net中基于Windows消息的IPC实现

在.net中基于Windows消息的IPC实现
2011年01月14日
  一、什么是IPC
  IPC(Inter process Communication)就是“进程间通讯”。我们都知道,在windows系统中,各个应用程序(进程)之间常常需要交换、传递数据,这就要解决进程间的数据通信问题。在最初的16位Windows3.x系统中,所有Windows应用程序共享单一地址,任何进程都能够对这一共享地址空间的数据进行读写操作。
  随着Windwos98、Windows NT、Windows2000等32位的操作系统的出现,每个进程都有自己的地址空间,一个Windows进程不能存取另一个进程的私有数据,也就是说,虽然两个进程可以用具有相同值的指针寻址,但所读写的只是它们各自的数据,这样就减少了进程之间的相互干扰。
  二、如何实现IPC
  那么在windows当前系统下,如何实现进程通讯呢?其实有很多方法,如:
  1、    剪贴板Clipboard
  2、    DDE(动态数据交换)
  3、    内存映像
  4、    消息管道
  5、    邮件槽
  6、    Socket
  7、    RPC
  8、    串行/并行通信(Serial/Parallel Communication)
  9、    COM/DCOM
  10、Windows消息
  三、基于Windows消息的IPC
  现在让我们进入今天我们要讲的主题:“基于Windows消息的IPC实现”。
  在这里,我假定大家对Windows消息机制都有很好的理解,所以我就不在这上面费太多的墨水了。我们直接看看Windows消息是怎么样实现进程间通讯的。我们首先看看Windows的消息常数:
  WM_COPYDATA=0x004A//  当一个应用程序传递数据给另一个应用程序时发送此消息。
  这就是我们要的。下面我们来看看如何利用它来实现IPC。
  让我们先看看几个API函数,没有它们,我们没有办法将数据发送出去。
  1、 PostMessage
  函数功能:该函数将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回。消息队列里的消息通过调用GetMessage和PeekMessage取得。
  函数原型:B00L PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
  参数
  hWnd:其窗口程序接收消息的窗口的句柄。可取有特定含义的两个值:
  HWND.BROADCAST:消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口。
  NULL:此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样。
  Msg:指定被寄送的消息。
  wParam:指定附加的消息特定的信息。
  IParam:指定附加的消息特定的信息。
  返回值:如果函数调用成功,返回非零值:如果函数调用失败,返回值是零。若想获得更多的错误信息,请调用GetLastError函数。
  2、 SendMessage
  函数功能:该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而函数PostMessage不同,将一个消息寄送到一个线程的消息队列后立即返回。
  函数原型:LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
  参数:
  hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
  Msg:指定被发送的消息。
  wParam:指定附加的消息指定信息。
  IParam:指定附加的消息指定信息。
  返回值:返回值指定消息处理的结果,依赖于所发送的消息。
  3、 RegisterWindowMessage
  函数功能:RegisterWindowMessage函数定义一个新的窗口消息,该消息保证在整个系统范围内是唯一的。调用SendMessage或PostMessage函数时可以使用该函数返回的消息值。
  函数原型:UINT RegisterWindowMessage(lpsz)
  参数:
  lpsz指向一个以NULL结束的字符串,该字符串指定待登记的消息。
  返回值:若成功地登记了消息,返回值是一个消息标识符。该标识符值的范围在0XC000到0XFFFF之间,否则,返回值为0。
  我们现在在C#中声明这些API函数:
  
  
          [DllImport("user32")]
  
  
          internal static extern int RegisterWindowMessage(string lpString);
  
  
          [DllImport("user32")]
  
  
          internal static extern int PostMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
  
  
          [DllImport("user32")]
  
  
          internal static extern int PostMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);
  
  
          [DllImport("user32")]
  
  
          internal static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
  然后定义一些我们需要的常数:
  
  
                  internal const int WM_COPYDATA = 0x004A; //当一个应用程序传递数据给另一个应用程序时发送此消息
  
  
          internal const int WM_DESTROY = 0x0002; //窗体被销毁
  
  
          internal const int WM_CREATE = 0x0001; //应用程序创建一个窗口
  
  
          internal const int WM_QUERYENDSESSION = 0x0011; //当