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包) ...
随机推荐
- JavaScript 最简单的图片切换
使用前在文件外部要有1.jpg 2.jpg 只是简单的模仿flash图片切换,可在此基础上引申出各种不同的效果. 思路: 建立一个数组存放图片的src,然后调用setInterval周期性的调用cha ...
- 报错:init: Could not find wglGetExtensionsStringARB!
如下操作即可恢复:
- Web 常用功能测试方法
功能测试就是对产品的各功能进行验证,根据功能测试用例,逐项测试,检查产品是否达到用户要求的功能.常用的测试方法如下: 1. 页面链接检查:每一个链接是否都有对应的页面,并且页面之间切换正确. 2. 相 ...
- 常用linux 命令 -字符串相关
参考网络文章,个人工作总结 题记:一般对字符串的操作有以下几种:求长度,截取字符串,拼接字符串,找字符串中某个字符的索引 1 expr 命令 1.1 定义 man 手册 Print the value ...
- nodeJS爬虫---慕课网
源代码一(爬取html源码) //引入http模块var http = require('http');//引入url地址var url = 'http://www.imooc.com/learn/2 ...
- 《jQuery判断radio、checkbox、select 是否选中和设置选中问题以及获取选中值》总结
<form> <input type="radio" name="gender" id="man" value=" ...
- Yii2 ActiveRecord save失败
当给AR写beforeSave方法时,注意返回true还是false.如果没有返回值,或者返回false,那么就不会存入数据库.如下 晚上写代码的时候beforeSave忘了返回true,导致无法存入 ...
- GSM07.10协议中串口复用使用的校验算法
] = { 0x00, 0x91, 0xE3, 0x72, 0x07, 0x96, 0xE4, 0x75, 0x0E, 0x9F, 0xED, 0x7C, 0x09, 0x98, 0xEA, 0x7B ...
- runtime 第四部分method swizzling
接上一篇 http://www.cnblogs.com/ddavidXu/p/5924597.html 转载来源http://www.jianshu.com/p/6b905584f536 http:/ ...
- C# socket send方法
转 http://msdn.microsoft.com/zh-cn/library/d318fkch(v=vs.80).aspx