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的更多相关文章

  1. MINIX3 进程通信分析

    MINIX3 进程通信分析 6.1MINIX3 进程通信概要 MINIX3 的进程通信是 MINIX3 内核部分最重要的一个部件,我个人认为其实这 是内核中的“内核”,怎么来理解这个概念呢?其实 MI ...

  2. [转]WINDOW进程通信的几种方式

    windows进程通信的几种方式 1 文件映射 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/O操作,只需简单的指针 ...

  3. Qt 的内部进程通信机制

    Qt 的内部进程通信机制 续欣 (xxin76@hotmail.com), 博士.大学讲师 2004 年 4 月 01 日 Qt 作为一种跨平台的基于 C++ 的 GUI 系统,能够提供给用户构造图形 ...

  4. Linux进程通信学习总结

    http://blog.csdn.net/xiaoweibeibei/article/details/6552498 SYSV子系统的相关概念   引用标识符:引用标识符是一个整数,表示每一个SYSV ...

  5. 【朝花夕拾】Android性能篇之(七)Android跨进程通信篇

    前言 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一.Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Andro ...

  6. python 守护进程、同步锁、信号量、事件、进程通信Queue

    一.守护进程 1.主进程创建守护进程 其一:守护进程会在主进程代码执行结束后就终止 其二:守护进程内无法再开启子进程,否则抛出异常:AssertionError: daemonic processes ...

  7. Android-Messenger跨进程通信

    http://blog.csdn.net/lmj623565791/article/details/47017485 一.概述 我们可以在客户端发送一个Message给服务端,在服务端的handler ...

  8. 初识网络进程通信<Heart.X.Raid>

    可以这样说:我们在网络上只做一件事,利用各种软件没完没了的相互通信. 对于单机系统而言,进程在系统中有自己唯一的进程号.但在网络环境下,各主机独立分配的进程号不能唯一标识该进程.例如,主机A赋于某进程 ...

  9. Linux之进程通信20160720

    好久没更新了,今天主要说一下Linux的进程通信,后续Linux方面的更新应该会变缓,因为最近在看Java和安卓方面的知识,后续会根据学习成果不断分享更新Java和安卓的方面的知识~ Linux进程通 ...

随机推荐

  1. 低调、奢华、有内涵的敏捷式大数据方案:Flume+Cassandra+Presto+SpagoBI

    基于FacebookPresto+Cassandra的敏捷式大数据 文件夹 1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 2 2.1 2.2 2.3 2.4 2.5 2.6 3 ...

  2. HDOJ 2647 Reward 【逆拓扑排序+分层】

    题意:每一个人的基础工资是888. 因为一部分人要显示自己水平比較高,要求发的工资要比其它人中的一个人多.问你能不能满足他们的要求,假设能的话终于一共要发多少钱,假设不能就输出-1. 策略:拓扑排序. ...

  3. Shell脚本:推断用户和用户组是否已经存在/创建用户和用户组

    通常作为一个应用程序的部署脚本,開始的第一项工作是为当前应用创建一个专用(dedicated)的用户和用户组.这个脚本非常easy.这里贴一个參考样本: #!/bin/sh user=test_use ...

  4. 2015.05.11,外语,读书笔记-《Word Power Made Easy》 15 “如何谈论事情进展” SESSION 44

    1. not the real McCoy simulate(['simjuleit] v. 假装,冒充,模仿,模拟)来自拉丁simulo,copy的意思.simulo本身派生自拉丁形容词simili ...

  5. 道里云SDN云网络技术:使云能够“众筹”

     容器云来了! 容器云的网络规模将比虚拟机云的情况扩大10-100倍,容器云与虚拟机云互联需求也将使云网络管控复杂度成数倍增长.SDN业界迎来了空前挑战.本报告分享道里云公司SDN技术:怎样将云的 ...

  6. GreenDao 3.X之基本使用

    在GreenDao 3.X之注解已经了解到GreenDao 3.0的改动及注解.对于数据库的操作,无异于增删改查等四个操作.下面我们将了解GreenDao 3.X如何使用? AbstractDao 所 ...

  7. java和android文件加密小结

    最近遇到一个文件加密的问题,自己读写的,安全性虽然还可以,但是速度慢,影响体验. Cipher虽然速度相当快,但是android和java有某些api存在不兼容: 问题解决: 方法引用自:https: ...

  8. C#获取URL参数值

    原文:C#获取URL参数值 在写程序的时候,我们经常需要对页面进行传参数,比如page?id=1234,那么在page这个页面中就直接可以使用string id = Request.QueryStri ...

  9. 【摘录】JAVA内存管理-有关垃圾收集的关键参数

    第八章 有关垃圾收集的关键参数 一些命令行参数可以用来选择垃圾收集器,指定堆或代的大小,修改垃圾收集行为,获取垃圾收集统计数据.本章给出一些最常用的参数.有关各种各样参数更多完整的列表和详细信息可以参 ...

  10. UVa 10106 Product 【大数相乘】WA

    虽然是错的代码,但是还是想贴出来,最开始WA发现是没有考虑到乘积为0的情况,后来把a*0,0*a,a*0---0(若干个0),0--0(若干个0)*a都考虑进去了:可是还是WA,实在不懂先留在这儿. ...