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 ...
随机推荐
- 读取spring配置文件的方法(spring读取资源文件)
1.spring配置文件 <bean id="configproperties" class="org.springframework.beans.factory. ...
- SPRING IN ACTION 第4版笔记-第三章ADVANCING WIRING-003-@Conditional根据条件生成bean及处理profile
一.用@Conditional根据条件决定是否要注入bean 1. package com.habuma.restfun; public class MagicBean { } 2. package ...
- 【Xamarin开发 Android 系列 4】 Android 基础知识
原文:[Xamarin开发 Android 系列 4] Android 基础知识 什么是Android? Android一词的本义指“机器人”,同时也是Google于2007年11月5日宣布的基于Li ...
- .net 利用 GZipStream 压缩和解压缩
1.GZipStream 类 此类在 .NET Framework 2.0 版中是新增的. 提供用于压缩和解压缩流的方法和属性 2.压缩byte[] /// <summary> /// 压 ...
- Codevs_1040_[NOIP2001]_统计单词个数_(划分型动态规划)
描述 http://codevs.cn/problem/1040/ 与Codevs_1017_乘积最大很像,都是划分型dp. 给出一个字符串和几个单词,要求将字符串划分成k段,在每一段中求共有多少单词 ...
- 【session】
users.json { "tobi": { "password": "ferret", "name": "T ...
- 【转】Mac OS X 快捷键(完整篇)
原文网址:http://www.nooidea.com/2011/01/mac-os-x-keyboard-shortcuts.html 没有写到基本的一些组合,只是一些可能大家不太常用到但及其提高机 ...
- The server is temporarily unable to service your request due to maintenance downtime or capacity problems. Please try again later.
The server is temporarily unable to service your request due to maintenance downtime or capacity pro ...
- Linux内核学习笔记1——系统调用原理【转】
1什么是系统调用 系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组“特殊”接口.用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文 ...
- Poj 3695-Rectangles 矩形切割
Rectangles Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 3846 Accepted: 1124 Descri ...