【转】 unity进程间通信 unity hook WM_COPYDATA

原贴:

unity3d进程通信利用WM_COPYDARE和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问我哦。里面很多大神也可以问。转载注重原创哦。

时间: 2024-12-11 22:51:24

【转】 unity进程间通信 unity hook WM_COPYDATA的相关文章

[Unity菜鸟] Unity鼠标双击,鼠标函数整理(未完)

1. 鼠标双击 ? 1 2 3 4 5 6 7 8 9 void OnGUI()    {        Event Mouse = Event.current;        if (Mouse.isMouse && Mouse.type == EventType.MouseDown && Mouse.clickCount == 2)        {            // 调用你的函数            print("Double Click&quo

Ubuntu 11.10 安装GMONE3,卸载 UNITY和UNITY 2D

Ubuntu 11.10安装GNOME3: 1)sudo apt-get install gnome-shell sudo apt-get install gnome-themes* (或者简单的选择 sudo apt-get install gnome-themes-standard) sudo apt-get install gnome-tweak-tool 2)sudo apt-get install gnome-session-fallback 卸载 UNITY和UNITY 2D: su

Unity手册-Unity概述

Unity概述 Unity是一个强大引擎,他自带的多种工具可以满足你多种需求. 这种编辑器是直观的可定制的,让你的工作更大的自由. 原文 Unity is a powerful engine with a variety of tools that can be utilised to meet your specific needs. The editor is intuitive and customisable allowing you a greater freedom in your

Microsoft.Practices.Unity AOP unity 3.x

上一文 Microsoft.Practices.Unity mvc controller 注入 本文记录为主,代码取自网络各大神,本地测试通过并记录在案. 内容:AOP 切面编程 核心代码:标的有注释 using Microsoft.Practices.Unity; using Microsoft.Practices.Unity.InterceptionExtension; using System; using System.Collections.Generic; using System.

「Unity」Unity中接入iOS、Android平台:第零篇,内容描述

从去年年末开始,我负责在Unity中建立 接入iOS.Android相关SDK 的模板工程,一路磕磕碰碰,填了很多坑,对其中的苦闷深有体会. 所以决定将自己填过的坑整理一下,让大家能够走得更顺畅,但未经本人同意,禁止转载,谢谢. 之后的篇章中将会包括以下内容(不断更新): 导出xCode工程目录结构的重点讲解 导出Android工程后目录结构的重点讲解 Android Studio工程的重点讲解 与iOS的简单数据交互.监听.回调 与Android的简单数据交互.监听.回调 Unity下用于数据

[Unity优化] Unity CPU性能优化 (难度3 推荐4)

原文地址: http://www.cnblogs.com/chwen/p/4396515.html 前段时间本人转战unity手游,由于作者(Chwen)之前参与端游开发,有些端游的经验可以直接移植到手游,比如项目框架架构.代码设计.部分性能分析,而对于移动终端而言,CPU.内存.显卡甚至电池等硬件因素,以及网络等条件限制,对移动游戏开发的优化带来更大的挑战. 这里就以unity4.5x版本为例,对Unity的优化方案做一个总结,有些是项目遇到的,也有些是看到别人写的不错拿来分享,算作一个整理,

Unity 通过Unity Admob Plugin插件集成admob教程

原创:officemaster.cn 下载Unity Admob Demo,插件里面包含Admob_Unity_Demo.unitypackage 插件文件AdmobPluginRes  是Admob 的ios sdk和插件使用样例代码打开样例代码可以看到代码里面如何使用Unity Admob插件 把Admob Unity插件添加进unity工程1. 打开Unity工程2. 从菜单打开,Assets -> Import Package -> Custom Package.3. 选中Unity插

Unity Optimization UNITY优化关注列表

这里主要罗列Unity引擎进行开发的应用或游戏,可以进行优化的各个关注点.(此文会持续更新) C# GC alloc Update LateUpdate Serialize String ToString() += Getter API Object.name GetComponents Sprite.vectices Debug.Log Closure anonymous function Unity API ParticleSystem Start Stop Pause Clear Simu

[Unity 笔记] unity中如何将Object序列化成xml字符串并保存

需要使用到以下这几个c#内置的命名空间. using System.Xml; using System.IO; using System.Xml.Serialization; 序列化并存储xml文件 XmlTextWriter xWrite = new XmlTextWriter(filename, null); XmlSerializer sl = new XmlSerializer(type); sl.Serialize(xWrite, target); xWrite.Close(); 读取