unity3d进程通信利用WM_COPYDATE和HOOK
hello,近期用unity做了进程通信,应该是和c++的PC端实现通信,才開始一头雾水,后来实现了才知道好繁杂......先感谢对我提供帮助的百度,谷歌以及游戏圈的大大们。
在进程通信中非常多方法,可是wm_copydate绝对要比别的什么内存共享好了很多。
unity大部分用c#语言,c#本身Forms这个dll里面也提供了对windows消息的接收可是在unity中无法非常好地使用System.Windows.Forms,所以在以下我的代码我用unity发送进程消息的是 user32.dll 中的sendMessage。对于接收则是用的hook(钩子)。
以下代码是unity打包出来的exe的通信。就不和c++通信了。原理都一样。
整个过程要导入user32.dll ,所以在须要using System.Runtime.InteropServices;剩下须要引用什么加入什么,里面还有发送json数据以及很多细节的c#取地址读取地址,我也一并分享大家乐,以后也要帮我哦.
发送端(利用sendMessage),test1.cs挂载在unity场景中
using System;
using UnityEngine;
using System.Collections;
using System.Runtime.InteropServices;
using System.Text; public class test15 : MonoBehaviour
{
#region
public IntPtr m_hWnd;
/// <summary>
/// 发送windows消息方便user32.dll中的SendMessage函数使用
/// </summary>
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
//user32.dll中的SendMessage
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, ref COPYDATASTRUCT lParam);
//user32.dll中的获得窗口句柄
[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string strClassName, string strWindowName);
//宏定义
private const ushort IPC_VER = 1;
private const int IDT_ASYNCHRONISM = 0x0201;
private const uint WM_COPYDATA = 0x004A;
private const ushort IPC_CMD_GF_SOCKET = 1;
private const ushort IPC_SUB_GF_SOCKET_SEND = 1;
private const int IPC_SUB_GF_CLIENT_READY = 1;
private const int IPC_CMD_GF_CONTROL = 2;
private const int IPC_BUFFER = 10240;//最大缓冲长度
//查找的窗口
private IntPtr hWndPalaz;
//数据包头配合使用
public unsafe struct IPC_Head
{
public ushort wVersion;
public ushort wPacketSize;
public ushort wMainCmdID;
public ushort wSubCmdID; }
public unsafe struct IPC_Buffer
{
public IPC_Head Head; //IPC_Head结构
public fixed byte cbBuffer[IPC_BUFFER]; //指针 存放json数据 利用byte[]接收存放
}
#endregion
/// <summary>
/// 发送把json转换为指针传到SendData()方法
/// </summary>
private void sendJson() {
IntPtr hWndPalaz = FindWindow(null, "你们要查找的窗口名字");//就是窗口的的标题
Debug.Log(hWndPalaz);
if (hWndPalaz != null)
{
//获得游戏本身句柄
m_hWnd = FindWindow("UnityWndClass", null); //发送用户准备好消息(这个是个json插件我就不提供了你们自己搞自己的json new一个实例这里不改会报错)
JSONObject jsStart = new JSONObject();
jsStart.AddField("六六", "是我");
jsStart.AddField("sya", "学习游戏为了装逼小组");
jsStart.AddField("doing", "this is your time"); string uRstr = jsStart.ToString();
byte[] bytes = Encoding.UTF8.GetBytes(uRstr);
IntPtr pData = Marshal.AllocHGlobal(2 * bytes.Length);
Marshal.Copy(bytes, 0, pData, bytes.Length);
SendData(m_hWnd, IPC_CMD_GF_SOCKET, IPC_SUB_GF_SOCKET_SEND, pData, (ushort)bytes.Length); } }
/// <summary>
/// SendMessage发送
/// </summary>
/// <param name="hWndServer">指针</param>
/// <param name="wMainCmdID">主命令</param>
/// <param name="wSubCmdID">次命令</param>
/// <param name="pData">json转换的指针</param>
/// <param name="wDataSize">数据大小</param>
/// <returns></returns>
public unsafe bool SendData(IntPtr hWndServer, ushort wMainCmdID, ushort wSubCmdID, IntPtr pData, ushort wDataSize)
{
//给IPCBuffer结构赋值
IPC_Buffer IPCBuffer;
IPCBuffer.Head.wVersion = IPC_VER;
IPCBuffer.Head.wSubCmdID = wSubCmdID;
IPCBuffer.Head.wMainCmdID = wMainCmdID;
IPCBuffer.Head.wPacketSize = (ushort)Marshal.SizeOf(typeof(IPC_Head)); //内存操作
if (pData != null)
{
//效验长度
if (wDataSize > 1024) return false;
//拷贝数据
IPCBuffer.Head.wPacketSize += wDataSize; byte[] bytes = new byte[IPC_BUFFER];
Marshal.Copy(pData, bytes, 0, wDataSize); for (int i = 0; i < IPC_BUFFER; i++)
{
IPCBuffer.cbBuffer[i] = bytes[i];
}
} //发送数据
COPYDATASTRUCT CopyDataStruct;
IPC_Buffer* pPCBuffer = &IPCBuffer;
CopyDataStruct.lpData = (IntPtr)pPCBuffer;
CopyDataStruct.dwData = (IntPtr)IDT_ASYNCHRONISM;
CopyDataStruct.cbData = IPCBuffer.Head.wPacketSize;
SendMessage(hWndServer, 0x004A, (int)m_hWnd, ref CopyDataStruct); return true;
}
void Update()
{
sendJson();//一直发送方便測试
}
}
接收端 test2.cs 随便建场景保存将这个脚本挂载场景的物体上面 。然后用unity打包pc端的exe 接收利用windows的hook钩子(这里我就不做具体的凝视了,自己体会hook的妙用了,不懂能够给我留言)
using UnityEngine;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Debug = UnityEngine.Debug;
public class test2: MonoBehaviour
{
//钩子接收消息的结构
public struct CWPSTRUCT
{
public int lparam;
public int wparam;
public uint message;
public IntPtr hwnd;
}
//建立钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, uint dwThreadId); //移除钩子
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook); //把信息传递到下一个监听
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, int wParam, int lParam);
//回调托付
private delegate int HookProc(int nCode, int wParam, int lParam);
//钩子
int idHook = 0;
//是否安装了钩子
bool isHook = false;
GCHandle gc;
private const int WH_CALLWNDPROC = 4; //钩子类型 全局钩子 //定义结构和发送的结构相应
public unsafe struct IPC_Head
{
public int wVersion;
public int wPacketSize;
public int wMainCmdID;
public int wSubCmdID;
}
private const int IPC_BUFFER = 10240;//最大缓冲长度
public unsafe struct IPC_Buffer
{
public IPC_Head Head;
public fixed byte cbBuffer[IPC_BUFFER]; //json数据存的地方
}
public struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
public IntPtr lpData;
}
void Start()
{
//安装钩子
HookLoad();
} void OnDestroy()
{
//关闭钩子
HookClosing();
}
private void HookLoad()
{
Debug.Log("開始执行");
//安装钩子
{
//钩子托付
HookProc lpfn = new HookProc(Hook);
//关联进程的主模块
IntPtr hInstance = IntPtr.Zero;// GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName);
idHook = SetWindowsHookEx(WH_CALLWNDPROC, lpfn, hInstance, (uint)AppDomain.GetCurrentThreadId());
if (idHook > 0)
{
Debug.Log("钩子[" + idHook + "]成功安装");
isHook = true;
//保持活动 避免 回调过程 被垃圾回收
gc = GCHandle.Alloc(lpfn);
}
else
{
Debug.Log("钩子安装失败");
isHook = false;
UnhookWindowsHookEx(idHook);
}
}
} //卸载钩子
private void HookClosing()
{
if (isHook)
{
UnhookWindowsHookEx(idHook);
}
} private bool _bCallNext;
public bool CallNextProc
{
get { return _bCallNext; }
set { _bCallNext = value; }
} //钩子回调 private unsafe int Hook(int nCode, int wParam, int lParam)
{ try
{
IntPtr p = new IntPtr(lParam);
CWPSTRUCT m = (CWPSTRUCT)Marshal.PtrToStructure(p, typeof(CWPSTRUCT)); if (m.message == 74)
{
COPYDATASTRUCT entries = (COPYDATASTRUCT)Marshal.PtrToStructure((IntPtr)m.lparam, typeof(COPYDATASTRUCT));
IPC_Buffer entries1 = (IPC_Buffer)Marshal.PtrToStructure((IntPtr)entries.lpData, typeof(IPC_Buffer)); IntPtr intp = new IntPtr(entries1.cbBuffer);
string str = new string((sbyte*)intp);
Debug.Log("json数据:" + str);
}
if (CallNextProc)
{
return CallNextHookEx(idHook, nCode, wParam, lParam);
}
else
{
//return 1;
return CallNextHookEx(idHook, nCode, wParam, lParam);
}
}
catch (Exception ex)
{
Debug.Log(ex.Message);
return 0;
} }
}
OK,全部代码最终特么的完成了。把test2.cs的场景打包。把test1.cs的代码放在unity执行即可了。最终看test2.cs的exe中的这些代码花了我好长时间,非常值钱的我就这么分享给大家了,希望大家有好的东西也不要吝啬啊。嘿嘿,最后有不懂的能够加我的Q群479853988问我哦。里面非常多大神也能够问。转载注重原创哦。
unity3d进程通信利用WM_COPYDATE和HOOK的更多相关文章
- MINIX3 进程通信分析
MINIX3 进程通信分析 6.1MINIX3 进程通信概要 MINIX3 的进程通信是 MINIX3 内核部分最重要的一个部件,我个人认为其实这 是内核中的“内核”,怎么来理解这个概念呢?其实 MI ...
- [转]WINDOW进程通信的几种方式
windows进程通信的几种方式 1 文件映射 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/O操作,只需简单的指针 ...
- Qt 的内部进程通信机制
Qt 的内部进程通信机制 续欣 (xxin76@hotmail.com), 博士.大学讲师 2004 年 4 月 01 日 Qt 作为一种跨平台的基于 C++ 的 GUI 系统,能够提供给用户构造图形 ...
- Linux进程通信学习总结
http://blog.csdn.net/xiaoweibeibei/article/details/6552498 SYSV子系统的相关概念 引用标识符:引用标识符是一个整数,表示每一个SYSV ...
- 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇
前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...
- python 守护进程、同步锁、信号量、事件、进程通信Queue
一.守护进程 1.主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes ...
- Android-Messenger跨进程通信
http://blog.csdn.net/lmj623565791/article/details/47017485 一.概述 我们可以在客户端发送一个Message给服务端,在服务端的handler ...
- 初识网络进程通信<Heart.X.Raid>
可以这样说:我们在网络上只做一件事,利用各种软件没完没了的相互通信. 对于单机系统而言,进程在系统中有自己唯一的进程号.但在网络环境下,各主机独立分配的进程号不能唯一标识该进程.例如,主机A赋于某进程 ...
- Linux之进程通信20160720
好久没更新了,今天主要说一下Linux的进程通信,后续Linux方面的更新应该会变缓,因为最近在看Java和安卓方面的知识,后续会根据学习成果不断分享更新Java和安卓的方面的知识~ Linux进程通 ...
随机推荐
- 再谈p2p投融资真相
近来亲自调查眼下各类p2p.重度调查对象有:人人贷.陆金所.前金所.开鑫贷.礼德財富.招財宝. 投资的有几个小观念: 首先,大家投资都习惯性的细分政府背景和非政府背景.说句实话,这对一个投资人角度来讲 ...
- 【WaaCaa】一款开源科学作图/数据可视化工具 —— 诞生篇
作为一个理工男.用过了形形色色能够用于科学作图/数据可视化软件:从大学时做实验课推荐用于分析简单採集数据的 Origin; 毕业论文时用来呈现实验时序信号和离线分析脑电信号的 MATLAB.后面还发现 ...
- json 与其他数据 格式转换及json学习新得
jsonobject var a={"a","A"} 通过json都对象能很轻松的操作json数据 jsonString var a=" ...
- 锋利Jquery 第一天
之前一直学习,现在终于有时间来整理一下文档了. 以下文章都是自己学习Jquery 的笔记, 希望能留下痕迹,也希望能帮助到您. 好了开始我的Jquery第一天. 我也是从Hello wrod!开始的 ...
- Linux就该这么学 20181010(第十四章DHCP)
参考链接:https://www.linuxprobe.com DHCP动态地址分配协议 作用域:定义一个很大的网段地址池:真正为用户去分配的地址地址池要小于等于作用域排除范围:作用域-地址池租约-默 ...
- 剑指offer——04重建二叉树(Python3)
思路:在数据结构中,有一个条件反射,谈及二叉树,就递归.所以在实现重建二叉树时,也应该用到递归的思想. 在前序遍历中,根节点处于第一个:在中序遍历中,根节点的左边为左子树节点,根节点右边为右子树节点. ...
- ios 中生成随机数
ios 有如下三种随机数方法: 1. srand((unsigned)time(0)); //不加这句每次产生的随机数不变 int i = rand() % 5; 2. s ...
- localStorage、sessionStorage、cookie、session
localStorage 和 sessionStorage HTML5 提供了两种在客户端存储数据的新方法:localStorage 和 sessionStorage: 两者都是仅在客户端(即浏览器) ...
- DOM基础知识(Node对象、Element对象)
5.Node对象 u 遍历节点 u 父节点 .parentNode - 获取父节点—> 元素节点或文档节点 .parentElement - 获取父元素节点—> 元素节点 u 子节 ...
- Codeforces 994A. Fingerprints
题意 从x数组中找到最多的y数组中有的数字,按在x数组中出现的顺序输出. 注意 这题x数组和y数组都不会出现重复数字. 代码 #include <bits/stdc++.h> using ...