首页 > 代码库 > unity3d进程通信利用WM_COPYDATE和HOOK

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 = http://www.mamicode.com/0x004A;>

    

接收端 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