winows 进程通信的实例详解
发送端:
新建一个基本对话框工程,添加6个文本框控件,并且关联控件变量(CString类型):
m_strCopyData, m_strFileMap, m_strMem,
m_strRegMsg, m_strUserMsg, m_strClipBoard
然后在 CPP 文件里面,做如下定义:
#define BUFFER_SIZE
0x100 // 用内存地址通信时分配的最大内存.
#define WM_COMM
WM_USER+100
const UINT
wm_nRegMsg=RegisterWindowMessage("reg_data");
const UINT
wm_nMemMsg=RegisterWindowMessage("mem_data");
添加6个按钮,在里面写入代码
//使用 WM_COPY 方式进行发送
void CDataSendDlg::OnSendCopydata()
{
UpdateData(); //更新数据.
CWnd
*pWnd=CWnd::FindWindow(NULL,_T("DataRecv")); // 查找DataRecv进程.
if(pWnd==NULL){
AfxMessageBox(TEXT("Unable to find DataRecv."));
return;
}
COPYDATASTRUCT cpd; // 给COPYDATASTRUCT结构赋值.
cpd.dwData = 0;
cpd.cbData =
m_strCopyData.GetLength();
cpd.lpData =
(void*)m_strCopyData.GetBuffer(cpd.cbData);
pWnd->SendMessage(WM_COPYDATA,NULL,(LPARAM)&cpd);// 发送.
}
//使用用户自定义消息的方式进行发送
void CDataSendDlg::OnSendUsermsg()
{
UpdateData(); // 更新数据.
CWnd
*pWnd=CWnd::FindWindow(NULL,_T("DataRecv")); // 查找DataRecv进程.
if(pWnd==NULL){
AfxMessageBox(TEXT("Unable to find DataRecv."));
return;
}
UINT uMsg;
uMsg=atoi(m_strUserMsg);
pWnd->SendMessage(WM_COMM,NULL,(LPARAM)uMsg);// 发送.
}
//使用用户注册消息的方式进行发送
void CDataSendDlg::OnSendRegmsg()
{
UpdateData(); // 更新数据.
CWnd
*pWnd=CWnd::FindWindow(NULL,_T("DataRecv")); // 查找DataRecv进程.
if(pWnd==NULL){
AfxMessageBox("Unable
to find DataRecv.");
return;
}
UINT uMsg;
uMsg=atoi(m_strRegMsg);
pWnd->SendMessage(wm_nRegMsg,NULL,(LPARAM)uMsg);// 发送.
}
//使用对目标进程内存的访问方式进行发送
void CDataSendDlg::OnSendMem()
{
UpdateData(); // 更新数据.
CWnd *pWnd=CWnd::FindWindow(NULL,_T("DataRecv"));
// 查找DataRecv进程.
if(pWnd==NULL){
AfxMessageBox("Unable to find DataRecv.");
return;
}
// 获取进程号.
DWORD PID;
GetWindowThreadProcessId(pWnd->m_hWnd, (DWORD*)&PID );
HANDLE hProcess = OpenProcess
(PROCESS_ALL_ACCESS,FALSE,PID);
// 分配虚拟内存.
LPVOID lpBaseAddress;
lpBaseAddress =
VirtualAllocEx(hProcess, 0, BUFFER_SIZE,
MEM_COMMIT,
PAGE_READWRITE);
char data[BUFFER_SIZE];
strcpy(data,m_strMem);
// 把字符串写入hProcess进程的内存.
WriteProcessMemory(hProcess,
lpBaseAddress, data, BUFFER_SIZE, NULL);
// 发送基址给DataRecv进程.
pWnd->SendMessage(wm_nMemMsg,NULL,(LPARAM)lpBaseAddress);
// 等待接收程序接收数据.
Sleep(100);
// 释放虚拟内存.
VirtualFreeEx(hProcess,lpBaseAddress, 0, MEM_RELEASE);
}
//使用内存映射的方式进行发送
void CDataSendDlg::OnSendFilemap()
{
UpdateData(); // 更新数据.
// 创建内存映像对象.
HANDLE hMapping;
LPSTR lpData;
hMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,NULL,
PAGE_READWRITE,0,BUFFER_SIZE,"MYSHARE");
if(hMapping==NULL)
{
AfxMessageBox("CreateFileMapping() failed.");
return;
}
// 将文件的视图映射到一个进程的地址空间上,返回LPVOID类型的内存指针.
lpData=(LPSTR)MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);
if(lpData==NULL)
{
AfxMessageBox("MapViewOfFile() failed.");
return;
}
// 给这段映像内存写数据.
sprintf(lpData,m_strFileMap);
// 释放映像内存.
UnmapViewOfFile(lpData);
}
//使用windows剪贴板的方式进行发送
void CDataSendDlg::OnSendClipboard()
{
UpdateData();
// 更新数据.
CString
strData=m_strClipBoard; // 获得数据.
// 打开系统剪贴板.
if (!OpenClipboard()) return;
// 使用之前,清空系统剪贴板.
EmptyClipboard();
// 分配一内存,大小等于要拷贝的字符串的大小,返回的内存控制句柄.
HGLOBAL hClipboardData;
hClipboardData =
GlobalAlloc(GMEM_DDESHARE, strData.GetLength()+1);
// 内存控制句柄加锁,返回值为指向那内存控制句柄所在的特定数据格式的指针.
char * pchData;
pchData = (char*)GlobalLock(hClipboardData);
// 将本地变量的值赋给全局内存.
strcpy(pchData,
LPCSTR(strData));
// 给加锁的全局内存控制句柄解锁.
GlobalUnlock(hClipboardData);
// 通过全局内存句柄将要拷贝的数据放到剪贴板上.
SetClipboardData(CF_TEXT,hClipboardData);
// 使用完后关闭剪贴板.
CloseClipboard();
}
至此,完成发送端
接收端:
新建一个基本对话框工程( DataRecv )
添加6个文本框控件,并且关联控件变量(CString类型):
m_strCopyData,m_strFileMap,m_strMem,m_strUserMsg,m_strRegMsg,m_strClipBoard
然后在 CPP 文件里面,做如下定义:
#define BUFFER_SIZE
0x100 // 用内存地址通信时分配的最大内存.
#define WM_COMM
WM_USER+100
const UINT
wm_nRegMsg=RegisterWindowMessage("reg_data");
const UINT
wm_nMemMsg=RegisterWindowMessage("mem_data");
添加两个按钮,并写入代码:
//控件 ID 为 IDC_RECV_CLIPBOARD 将取得的值赋给 m_strFileMap
//使用windows剪贴板的方式进行接收
void CDataRecvDlg::OnBnClickedRecvClipboard()
{
// TODO: 在此添加控件通知处理程序代码
// 打开系统剪贴板.
if (!OpenClipboard()) return;
// 判断剪贴板上的数据是否是指定的数据格式.
if
(IsClipboardFormatAvailable(CF_TEXT)|| IsClipboardFormatAvailable(CF_OEMTEXT))
{
// 从剪贴板上获得数据.
HANDLE hClipboardData
= GetClipboardData(CF_TEXT);
// 通过给内存句柄加锁,获得指向指定格式数据的指针.
char
*pchData = (char*)GlobalLock(hClipboardData);
// 本地变量获得数据.
m_strClipBoard = pchData;
// 给内存句柄解锁.
GlobalUnlock(hClipboardData);
}
else
{
AfxMessageBox("There is no text (ANSI) data on the Clipboard.");
}
// 使用完后关闭剪贴板.
CloseClipboard();
// 更新数据.
UpdateData(FALSE);
}
//控件 ID 为 IDC_RECV_FILEMAP, 将取得的值赋给 m_strClipBoard
//使用内存映射的方式进行接收
void CDataRecvDlg::OnBnClickedRecvFilemap()
{
// TODO: 在此添加控件通知处理程序代码
// 创建内存映像对象.
HANDLE hMapping;
LPSTR lpData;
hMapping=CreateFileMapping((HANDLE)0xFFFFFFFF,
NULL,PAGE_READWRITE,0,0x100,"MYSHARE");
if(hMapping==NULL)
{
AfxMessageBox("CreateFileMapping() failed.");
return;
}
// 将文件的视图映射到一个进程的地址空间上,返回LPVOID类型的内存指针.
lpData=(LPSTR)MapViewOfFile(hMapping,FILE_MAP_ALL_ACCESS,0,0,0);
if(lpData==NULL)
{
AfxMessageBox("MapViewOfFile() failed.");
return;
}
// 给这段映像内存的数据赋给本地变量.
m_strFileMap.Format("%s",lpData);
// 释放映像内存.
UnmapViewOfFile(lpData);
// 更新数据.
UpdateData(FALSE);
}
然后在 DataRecvDlg.cpp 中添加消息映射
BEGIN_MESSAGE_MAP(CDataRecvDlg, CDialog)
//}}AFX_MSG_MAP
ON_BN_CLICKED(IDC_RECV_CLIPBOARD,
OnBnClickedRecvClipboard)
ON_BN_CLICKED(IDC_RECV_FILEMAP, OnBnClickedRecvFilemap)
ON_WM_COPYDATA()
ON_MESSAGE(WM_COMM,OnUserReceiveMsg)
ON_REGISTERED_MESSAGE(wm_nRegMsg,OnRegReceiveMsg)
ON_REGISTERED_MESSAGE(wm_nMemMsg,OnRegMemMsg)
END_MESSAGE_MAP()
在 DataRecvDlg.h 中添加响应消息
afx_msg BOOL OnCopyData(CWnd* pWnd,
COPYDATASTRUCT* pCopyDataStruct);
afx_msg LRESULT OnUserReceiveMsg(WPARAM wParam,LPARAM
lParam);
afx_msg LRESULT OnRegReceiveMsg(WPARAM
wParam,LPARAM lParam);
afx_msg LRESULT OnRegMemMsg(WPARAM wParam,LPARAM
lParam);
最后在 DataRecvDlg.cpp 中补全消息相应函数
//使用 WM_COPY 方式进行接收
BOOL CDataRecvDlg::OnCopyData(CWnd* pWnd,
COPYDATASTRUCT* pCopyDataStruct)
{
m_strCopyData=(LPSTR)pCopyDataStruct->lpData;
// 获得实际长度的字符串.
m_strCopyData=m_strCopyData.Left(pCopyDataStruct->cbData);
// 更新数据.
UpdateData(FALSE);
return
CDialog::OnCopyData(pWnd, pCopyDataStruct);
}
//使用用户自定义消息的方式进行接收
LRESULT CDataRecvDlg::OnUserReceiveMsg(WPARAM
wParam,LPARAM lParam)
{
m_strUserMsg.Format("%d\n",int(lParam));
// 更新数据.
UpdateData(FALSE);
return TRUE;
}
//使用用户注册消息的方式进行接收
LRESULT CDataRecvDlg::OnRegReceiveMsg(WPARAM
wParam,LPARAM lParam)
{
m_strRegMsg.Format("%d\n",int(lParam));
// 更新数据.
UpdateData(FALSE);
return TRUE;
}
//使用对目标进程内存的访问方式进行接收
LRESULT CDataRecvDlg::OnRegMemMsg(WPARAM
wParam,LPARAM lParam)
{
LPVOID
lpBaseAddress=(LPVOID)lParam;
// 把字符串写入hProcess进程的内存.
HANDLE
hProcess=GetCurrentProcess();
char data[BUFFER_SIZE];
ReadProcessMemory(hProcess,
lpBaseAddress, data,BUFFER_SIZE, NULL);
m_strMem=data;
// 更新数据.
UpdateData(FALSE);
return TRUE;
}
至此,完成接收端
需要注意的是,接收端必须先运行,用户自定义消息、注册消息只能发送长整型的数据,其他方式可以发送字符串数据.使用 内存映射 和 windows剪贴板 进行数据接收时,需要点击按纽才能接收到数据,其他方式会自动接收数据.
winows 进程通信的实例详解的更多相关文章
- Python进程和线程实例详解
前言 进程是什么? 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数据集则是程序在执行过程中所需 ...
- Android跨进程通信:图文详解 Binder机制 原理
binder原理讲的很详细 https://blog.csdn.net/carson_ho/article/details/73560642
- 「微信小程序」PHP异步进程async-helper实例详解
PHP异步进程async-helper实例详解 PHP 的异步进程助手,借助于 AMQP 实现异步执行 PHP 的方法,将一些很耗时.追求高可用.需要重试机制的操作放到异步进程中去执行,将你的 HTT ...
- Cocos2d-x 3.X手游开发实例详解
Cocos2d-x 3.X手游开发实例详解(最新最简Cocos2d-x手机游戏开发学习方法,以热门游戏2048.卡牌为例,完整再现手游的开发过程,实例丰富,代码完备,Cocos2d-x作者之一林顺和泰 ...
- Linux下rz命令使用的实例详解
Linux中rz命令和sz命令都可用于文件传输,而rz命令主要用于文件的上传,下面将通过几个实例来给大家详细介绍下Linux下rz命令的用法,一起来学习下吧. rz命令可以批量上传文件,当然也可上传单 ...
- PHP多进程编之pcntl_fork的实例详解
PHP多进程编之pcntl_fork的实例详解 其实PHP是支持并发的,只是平时很少使用而已.平时使用最多的应该是使用PHP-FMP调度php进程了吧. 但是,PHP的使用并不局限于做Web,我们完全 ...
- expect学习笔记及实例详解【转】
1. expect是基于tcl演变而来的,所以很多语法和tcl类似,基本的语法如下所示:1.1 首行加上/usr/bin/expect1.2 spawn: 后面加上需要执行的shell命令,比如说sp ...
- linux基础-磁盘阵列(RAID)实例详解
磁盘阵列(RAID)实例详解 raid技术分类 软raid技术 硬raid技术 Raid和lvm的区别 为什么选择用raid RAID详解 RAID-0 RAID-1 RAID-5 Raid-10 R ...
- JavaScript学习笔记-实例详解-类(二)
实例详解-类(二) //===给Object.prototype添加只读\不可枚举\不可配置的属性objectId(function(){ Object.defineProperty(Object ...
随机推荐
- Visual Studio快捷键小结
工欲善其事必先利其器,这句话相信大家都听说过.利其器,就是我们先得有个神器,神器就是VS(号称宇宙第一IDE),有了神奇不会用也是白搭,就像你有了倚天剑和屠龙刀你不会使,它也就是废铁(假设它们是铁做的 ...
- jquery mobile backbone
http://www.appliness.com/getting-started-with-html-mobile-application-development-using-jquery-mobil ...
- 带你了解世界最先进的手势识别技术 -- 微软,凌感,Leap...
转载 今天为大家解释一下现有的几种主要的手势识别技术,为你揭开手势识别技术的神秘面纱. 概述 谈起手势识别技术,由简单粗略的到复杂精细的,大致可以分为三个等级:二维手型识别.二维手势识别.三维手势识别 ...
- 运行 maven install的时候出现错误 not a jre
原文转自jingyan.baidu.com/article/c85b7a6464d8be003bac95fb.html (linux下我直接执行第二步,错误解决) 在使用eclipse 运行 mave ...
- leetcode面试准备:Divide Two Integers
leetcode面试准备:Divide Two Integers 1 题目 Divide two integers without using multiplication, division and ...
- ajax 初始化请求前携带参数
$(function () { function SetAjax(wxOpenId, departCode) { $.ajaxSetup({ xhrF ...
- Android之读取 AndroidManifest.xml 中的数据
转:http://www.2cto.com/kf/201208/151123.html 下来示例如何读取这些数据. 1 版本信息.应用名称 2 Appliction 的Meta-data 3 Acti ...
- wcf异常汇总
1.确保客户端可以接收到服务端的异常 2.部署wcf出错,http错误404.3 3.无法自动调试 未能调试远程过程.这通常说明未在服务器上启用调试 WCF 托管在IIS上 4.ChannelFact ...
- Devexpress 之gridControl
1.gridControl如何去掉主面板? 鼠标右键Run Designer=>OptionsView => ShowGroupPanel=False: 2.gridControl如何设置 ...
- 使用socket.io打造公共聊天室
最近的计算机网络课上老师开始讲socket,tcp相关的知识,当时脑袋里就蹦出一个想法,那就是打造一个聊天室.实现方式也挺多的,常见的可以用C++或者Java进行socket编程来构建这么一个聊天室. ...