WM_COPYDATA实现的不同进程间通信
一、找到新软件需被通知的窗口(一般是以配置的形式实现)
二、发送消息
三、将对象序列化为字符串及反序列化的操作,通过一个帮助类实现
Demo代码:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;
namespace Dralee.AppTransferMsg.Common
{
[Serializable]
public class Msg
{
public string SentBy { get; set; }
public string RcvBy { get; set; }
public string Message { get; set; }
public DateTime SentOn { get; set; }
public Msg()
{
}
public Msg(string sentBy, string rcvBy, string msg, DateTime sentOn)
{
SentBy = sentBy;
RcvBy = rcvBy;
Message = msg;
SentOn = sentOn;
}
public static byte[] Serialize(Msg msg)
{
MemoryStream ms = new MemoryStream();
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, msg);
byte[] buffer = ms.GetBuffer();
ms.Close();
return buffer;
//return Encoding.Unicode.GetString(buffer);
}
public static Msg Deserialize(byte[] buffer)
{
MemoryStream ms = new MemoryStream(buffer);
BinaryFormatter bf = new BinaryFormatter();
Msg msg = (Msg)bf.Deserialize(ms);
return msg;
}
}
/// <summary>
/// 传输结构
/// </summary>
public struct CopyDataStruct
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
}
转换帮助类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Dralee.AppTransferMsg.Common
{
// CreatedBy: Jackie Lee
// CreatedOn: 2016-08-17
/// <summary>
/// 字节数组与字符串互转
/// </summary>
public class HexConverter
{
/// <summary>
/// 字节数组转
/// </summary>
/// <param name="buffer"></param>
/// <returns></returns>
public string ByteToString(byte[] buffer)
{
StringBuilder sb = new StringBuilder();
for(int i = ; i < buffer.Length; ++i)
{
sb.AppendFormat("{0:X2}", buffer[i]);
}
return sb.ToString();
}
/// <summary>
/// 字符串转字节数组
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public byte[] StringToByte(string str)
{
if(string.IsNullOrEmpty(str) || str.Length % != )
{
return null;
}
byte[] buffer = new byte[str.Length / ];
string hex;
int j = ;
for(int i = ; i < buffer.Length;++i)
{
hex = new string(new char[] { str[j], str[j + ]});
buffer[i] = HexToByte(hex);
j += ;
}
return buffer;
}
/// <summary>
/// 双字节字符转byte
/// </summary>
/// <param name="hex"></param>
/// <returns></returns>
public byte HexToByte(string hex)
{
if (hex.Length > )
return ;
char[] hexs = hex.ToArray();
if(hexs.Length == )
{
return (byte)NumByChar(hexs[]);
}
else
{
return (byte)(NumByChar(hexs[]) * + NumByChar(hexs[]));
}
}
private byte NumByChar(char ch)
{
switch(ch)
{
case '': return ;
case '': return ;
case '': return ;
case '': return ;
case '': return ;
case '': return ;
case '': return ;
case '': return ;
case '': return ;
case '': return ;
case 'A': return ;
case 'B': return ;
case 'C': return ;
case 'D': return ;
case 'E': return ;
case 'F': return ;
default:
return ;
}
}
}
}
API类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace Dralee.AppTransferMsg.Common
{
public static class API
{
public const int WM_COPYDATA = 0x004A;
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
/// <summary>
/// 发送消息
/// </summary>
/// <param name="hwnd">目标句柄</param>
/// <param name="msg"></param>
/// <param name="wParam">参数1</param>
/// <param name="lParam">参数2</param>
/// <returns></returns>
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hwnd, int msg, int wParam, ref CopyDataStruct lParam);
}
}
发送端:
private void btnSend_Click(object sender, EventArgs e)
{
Msg msg = new Msg { SentBy = txtSentBy.Text.Trim(), RcvBy = txtRcvBy.Text.Trim(), Message = txtMsg.Text.Trim(), SentOn = DateTime.Parse(txtSentOn.Text) };
//long size = GC.GetTotalMemory(true);
int hwnd = API.FindWindow(null, "(测试)->接收者");
if (hwnd == )
return;
string msgStr = new HexConverter().ByteToString(Msg.Serialize(msg));
CopyDataStruct cds;
cds.dwData = (IntPtr);
cds.cbData = (int)msgStr.Length + ;
cds.lpData = msgStr; API.SendMessage(hwnd, API.WM_COPYDATA, ,ref cds);
}
接收端,通过重写以实现对消息监控:
protected override void DefWndProc(ref Message m)
{
switch(m.Msg)
{
case API.WM_COPYDATA:
CopyDataStruct cds = (CopyDataStruct)m.GetLParam(typeof(CopyDataStruct));
//Msg msg = (Msg)m.GetLParam(typeof(Msg));
byte[] buffer = new HexConverter().StringToByte(cds.lpData);
Msg msg = Msg.Deserialize(buffer);
txtMsg.Text = msg.Message;
txtRcvBy.Text = msg.RcvBy;
txtSentBy.Text = msg.SentBy;
txtSentOn.Text = msg.SentOn.ToLongDateString();
break;
default:
base.DefWndProc(ref m);
break;
}
}
效果:

WM_COPYDATA实现的不同进程间通信的更多相关文章
- WM_COPYDATA+BHO+Qt实现进程间通信
最近项目有一个需求:点击网页上某个按钮,通知Qt客户端.网页相关操作使用了BHO,BHO与Qt通信通过WB_COPYDATA,为什么这么麻烦呢,因为项目正好用到了BHO,可能还有其他方式,能直接通过网 ...
- WM_COPYDATA进程间通信方案
连续在两个公司使用WM_COPYDATA实现进程间通信了,整理一下 具体步骤: 一. 进程A通过ShellExecute启动进程B, 将用于通信的窗口句柄hWndA(已强转为int值)通过命令行参 ...
- 【IPC进程间通信之四】数据复制消息WM_COPYDATA
IPC进程间通信+数据复制消息WM_COPYDATA IPC(Inter-Process Communication,进程间通信). 数据复制消息WM_C ...
- 利用WM_COPYDATA消息实现进程间通信
进程间通信最简单的方式就是发送WM_COPYDATA消息,下面通过例子来实现. 发送WM_COPYDATA消息: SendMessage(hRecvWnd, WM_COPYDATA, (WPARAM) ...
- 进程间通信之WM_COPYDATA方式反思,回顾和总结
许多Windows程序开发者喜欢使用WM_COPYDATA来实现一些进程间的简单通信(笔者也正在学习共享内存的一些知识来实现一些更高级的通信),这篇文章描述了笔者在使用这项技术时候的一些总结以及所遇到 ...
- 进程间通信的WM_COPYDATA的使用
http://blog.csdn.net/ao929929fei/article/details/6316174 接收数据的一方 ON_WM_COPYDATA() afx_msg BOOL OnCop ...
- 利用WM_COPYDATA进行进程间通信
发信消息 void CControlDlg::OnBnClickedButtonSend() { // TODO: 在此添加控件通知处理程序代码 CString strWindowTitle = _T ...
- CE 进程间通信
WINCE下进程间通信常用的方式有:剪贴板(Clipboard),网络套接字(Socket),WM_COPYDATA消息,共享内存,管道(消息队列),注册表等 剪贴板 //////////////// ...
- [转]Windows进程间通信的各种方法
http://www.cnblogs.com/songQQ/archive/2009/06/03/1495764.html 道相似,不过它传输数据是通过不可靠的数据报(如TCP/IP协议中的UDP包) ...
随机推荐
- PowerShell Notes
1. 概要 - PowerShell 是cmdlet(command-let)的指令集合,类似unix的bash. - IDE: Windows PowerShell ISE,不区分大小写,可以用命 ...
- XSS的防御
基于代码修改的防御 和SQL注入防御一样,XSS攻击也是利用了Web页面的编写疏忽,所以还有一种方法就是从Web应用开发的角度来避免: 步骤1.对所有用户提交内容进行可靠的输入验证,包括对URL.查询 ...
- 解决自定义leftBarButtonItem返回手势失效的方法
考虑到interactivePopGestureRecognizer也有delegate属性,替换默认的self.navigationController.interactivePopGestureR ...
- 室内定位系列(三)——位置指纹法的实现(KNN)
位置指纹法中最常用的算法是k最近邻(kNN):选取与当前RSS最邻近的k个指纹的位置估计当前位置,简单直观有效.本文介绍kNN用于定位的基本原理与具体实现(matlab.python). 基本原理 位 ...
- 吐槽贴:百度地图 api 封装 的实用功能 [源码下载]
ZMap 类 功能介绍 ZMap 是学习百度地图 api 接口,开发基本功能后整的一个脚本类,本类方法功能大多使用 prototype 原型 实现: 包含的功能有:轨迹回放,圈画区域可编辑,判断几个坐 ...
- 利用beans.xml进行简单的Spring应用上下文创建与使用
继上次配置Spring完成后,我们来创建一个简单的例程来理解Spring中利用beans.xml创建应用上下文的方法. 程序路径包为:com.spring.kinghts(kinght单词拼写错误,怕 ...
- Hibernate简易原生DAO的实现
写在最前: 初学Hibernate,在尝试把JDBC项目移植到Hibernate的过程中,碰到了不少的麻烦,最让人心烦意乱的自然是SQL语句改动造成的代码混乱.其实不难,网上的解决方案有很多, 不过. ...
- secureCRT The remote system refused the connection.
转 http://blog.csdn.net/lifengxun20121019/article/details/13627757 我在实践远程登录工具SecureCRT的时候遇到了这个问题 Ubun ...
- 耿丹CS16-2班第七次作业汇总
Deadline: 2016-11-27 11:59pm 作业内容 第七次作业总结 01.每次成绩发布,麻烦没交作业的同学(暂定得分为-5的),请及时补交: 02.想不出来可以,代码乱成一团不行,命名 ...
- mysql的enum和set数据类型
定义一个ENUM或者SET类型,可以约束存入的数值. ENUM中的值必须是定义过数值列中的一个,比如ENUM('a','b','c'),存入的只能是'a'或者'b'或者'c',如果存入'','d'或者 ...