博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WM_COPYDATA实现进程间通信
阅读量:3979 次
发布时间:2019-05-24

本文共 2793 字,大约阅读时间需要 9 分钟。

      在用Shuttle ESB完成C++程序和C#程序消息推送时,需要完成C++进程和ESB进程的通信问题。

  进程间的通信方式有很多,比如使用内存映射文件、通过共享内存DLL共享内存、使用消息队列MSMQ、使用SendMessage向另一进程发送WM_COPYDATA消息。比起前几种的复杂实现来,WM_COPYDATA消息无疑是一种经济实惠的一中方法。  

  下面讲解如何通过WM_COPYDATA进行进行通信及通信原理。

  1.建立SendMessage方法需要引用的数据结构:

namespace Entity{    public class ReceiveMessage    {        public struct CopyDataStruct        {            public IntPtr dwData;            public int cbData;            [MarshalAs(UnmanagedType.LPStr)]            public string lpData;        }    }}
 
 2.在进程A和进程B分别对类库Entity进行引用:

  3.在发送方构造SendMessage方法:

[DllImport("User32.dll", EntryPoint = "SendMessage")]        private static extern int SendMessage(int hWnd, int Msg, int wParam, ref Entity.ReceiveMessage.CopyDataStruct lParam);        [DllImport("User32.dll", EntryPoint = "FindWindow")]        private static extern int FindWindow(string lpClassName, string lpWindowName);        const int WM_COPYDATA = 0x004A; private void btnSend_Click(object sender, EventArgs e)        {            int hWnd = FindWindow(null, @"frmReceiver");            if (hWnd == 0)            {                MessageBox.Show("未找到消息接受者!");            }            else            {                byte[] sarr = System.Text.Encoding.Default.GetBytes(txtStr.Text);                int len = sarr.Length;                Entity.ReceiveMessage.CopyDataStruct cds;                cds.dwData = (IntPtr)Convert.ToInt16(txtInt.Text);//可以是任意值                cds.cbData = len + 1;//指定lpData内存区域的字节数                cds.lpData = txtStr.Text;//发送给目标窗口所在进程的数据                SendMessage(hWnd, WM_COPYDATA, 0, ref cds);            }        }

  SendMessage包含4个参数,hWnd:目标进程句柄,wMsg:用于区分其他消息的常量值,wParam:与消息有关的常量值,lParam:指向内存中数据的指针。

  换成咱们的话就是:当前进程通过wMsg这种消息方式把lParam指向的内存数据传递到句柄为hWnd的进程中。

           WM_COPYDATA的常量值0x004A代表“当一个应用程序传递数据给另一个应用程序时发送此消息”,WM不同的常量值代表不同的消息,更多WM_常量可以参考文章:。WM_COPYDATA的常量值必须为0x004A,SendMessage才能完成进程消息传递,否则接收方可以检测到有消息到达,但无法接收消息内容。

  4.在接收方通过DefWndProc回调方法完成消息捕获:

protected override void DefWndProc(ref Message m)        {            switch (m.Msg)            {                case WM_COPYDATA:                    Entity.ReceiveMessage.CopyDataStruct cds = new Entity.ReceiveMessage.CopyDataStruct();                    Type t = cds.GetType();                    cds = (Entity.ReceiveMessage.CopyDataStruct)m.GetLParam(t);                    string strResult = cds.dwData.ToString() + ":" + cds.lpData;                    txtReceiver.Text = strResult;                    break;                default:                    base.DefWndProc(ref m);                    break;            }        }
         
进程通信必须先启动接收方程序,因为发送方发送数据时需要检测接收方的句柄是否存在。SendMessage函数为阻塞式通信,当发送方的SendMessage函数开始执行时,接收方的DefWndProc函数会自动捕获发送方发送的数据。当DefWndProc函数执行完毕后,SendMessage函数才会继续执行。
  这篇文章讲解的是如何模拟C++程序,将C++程序检测到的硬件数据通过WM_COPYDATA消息传送到ESB,下篇将会讲解ESB如何将数据通过观察者模式推送到各个客户端,大家敬请期待。

转载地址:http://ixkui.baihongyu.com/

你可能感兴趣的文章
vi和vim区别
查看>>
程序员经典语录
查看>>
Django性能优化
查看>>
python模块学习 ---- smtplib 邮件发送
查看>>
Python模块学习 ---- subprocess 创建子进程
查看>>
python求时间差
查看>>
Python网页抓取urllib,urllib2,httplib[2]
查看>>
Python urllib2递归抓取某个网站下图片
查看>>
JS清空多文本框|文本域
查看>>
linux常用命令(操作命令)
查看>>
Linux一些经典书籍
查看>>
apache启动报错(98)Address already in use: make_sock: could not bind to address [::]:80
查看>>
linux kill用法、killall、pkill、xkill
查看>>
Python笔记——排序算法的实现
查看>>
jQuery数据显示插件整合实现代码
查看>>
python时区设置——pytz模块
查看>>
用datetime和pytz来转换时区
查看>>
python解决导出excel文件时中文文件名乱码
查看>>
Django操作NOSQL(MongoDB)数据库
查看>>
Failed to load JavaHL Library
查看>>