WM_COPYDATA实现进程通信

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

进程间的通信方式有很多,比如使用内存映射文件、通过共享内存DLL共享内存、使用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_常量部分说明。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如何将数据通过观察者模式推送到各个客户端,大家敬请期待。

时间: 10-16

WM_COPYDATA实现进程通信的相关文章

unity3d进程通信利用WM_COPYDATE和HOOK

hello,近期用unity做了进程通信,应该是和c++的PC端实现通信,才開始一头雾水,后来实现了才知道好繁杂......先感谢对我提供帮助的百度,谷歌以及游戏圈的大大们. 在进程通信中非常多方法,可是wm_copydate绝对要比别的什么内存共享好了很多. unity大部分用c#语言,c#本身Forms这个dll里面也提供了对windows消息的接收可是在unity中无法非常好地使用System.Windows.Forms,所以在以下我的代码我用unity发送进程消息的是 user32.dl

第七课 进程通信

unix_c_07.txt================第七课 进程通信================一.基本概念------------1. 何为进程间通信~~~~~~~~~~~~~~~~~进程间通信(Interprocess Communication, IPC)是指两个,或多个进程之间进行数据交换的过程.2. 进程间通信分类~~~~~~~~~~~~~~~~~1) 简单进程间通信:命令行参数.环境变量.信号.文件.2) 传统进程间通信:管道(fifo/pipe).3) XSI进程间通信:

进程通信——匿名管道

有的时候在程序的开发过程中,两个进程之间会有数据的交互.信号的机制能够实现进程通信.它通过 “中断--响应” 的异步模式来工作.但作为通信来讲,信号还是远远不够的.因为它不能够携带任何其他的信息.只利用信号机制来实现进程通信显得捉襟见肘,并且信号的优势并不此.所以必须开发新的进程间通信的方法.本文所学习的 "匿名管道" 便是其中的一种最简单的方法. 基本概念 在讲管道的基本概念之前,首先提一个问题.如果让你来设计进程通信的方式,你会怎么做?最简单的方式莫过于两个进程打开同一个文件,这样

Socket进程通信机制

1.Socket通常称为"套接字",用于描述IP地址和端口,是一个通信链的句柄. 2.应用程序通过套接字向网络发出请求或者应答网络请求. 3.Socket既不是一个程序,也不是一种协议,其只是操作系统提供的通信层的一组抽象API. 4.进程通信的相关概念: 网间进程通信要解决的是不同主机进程间相互通信问题.为此,首先要解决的是网间进程标识问题.同一主机上,不同进程可用唯一进程号(Process ID)标识. (1)端口:网络中可以被命名和寻址的通信端口,是操作系统可分配的一种资源,用于

android 远程Service以及AIDL的跨进程通信

在Android中,Service是运行在主线程中的,如果在Service中处理一些耗时的操作,就会导致程序出现ANR. 但如果将本地的Service转换成一个远程的Service,就不会出现这样的问题了. 转换成远程Service非常简单,只需要在注册Service的时候将他的android:process的属性制定成 :remote就可以了. 重新运行项目,你会发现,不会出现ANR了. 为什么将MyService转换成远程Service后就不会导致程序ANR了呢?这是由于,使用了远程Serv

进程通信之内存共享篇

进程通信之_ 内存共享 概念:共享内存是被多个进程共享的一部分物理内存.共享内存是进程间的共享数最快的方法,一个进程向共享内存区域写入数据,共享这个内存区域的所有进程就可以写入数据,所有进程就可以立刻看到其中的内容. 实现步骤;1.创建共享内存,使用shmget函数2.映射共享内存,将这段创建的共享内存映射到具体的进程空间去,使用shmat函数 创建:int shmget (key_t key,int size,int shmflg)key 标识内存功效的键值0/ipc_private.成功返回

Windows进程通信 -- 共享内存

享内存的方式原理就是将一份物理内存映射到不同进程各自的虚拟地址空间上,这样每个进程都可以读取同一份数据,从而实现进程通信.因为是通过内存操作实现通信,因此是一种最高效的数据交换方法. 共享内存在 Windows 中是用 FileMapping 实现的,从具体的实现方法上看主要通过以下几步来实现: 1.调用 CreateFileMapping 创建一个内存文件映射对象: HANDLE CreateFileMapping( HANDLE hFile, // handle to file to map

进程通信(二)—— 信号量&内存共享

内存共享是进程间常用的通信方式,可以实现两个完全独立的进程通信. 在访问共享内存时,同时需要信号量进行访问控制. 使用ipcs -m命令可以查看系统共享内存,ipce -m + key 可以删除指定的共享内存. 对共享内存操作时,使用信号量对共享内存进行保护,类似与线程中的互斥锁.都可以看做是通过PV操作实现临界资源保护. P:对信号量标记位-1,获取信号量,如果标记位为0,表示有其他进程占用资源,无法获取. V:对信号量标记位+1,释放信号量,将资源释放,给其他进程使用. 信号量和内存共享需要

初始网络进程通信

可以这样说:我们在网络上只做一件事,利用各种软件没完没了的相互通信. 对于单机系统而言,进程在系统中有自己唯一的进程号.但在网络环境下,各主机独立分配的进程号不能唯一标识该进程.例如,主机A赋于某进程号5,在B机中也可以存在5号进程,因此,“5号进程”这句话就没有意义了.而且 操作系统支持的网络协议众多,不同协议的工作方式不同,地址格式也不同.因此,网间进程通信还要解决多重协议的识别问题. 为此,TCP/IP协议为网间进程通信问题建立了IP地址,端口,Socket(套接字)等概念.      (