欢迎光临散文网 会员登陆 & 注册

在Windows平台上。使用Sendmessage方法实现Unity不同进程之间通信

2023-03-02 17:56 作者:吴糖江茶  | 我要投稿

在Windows平台上。使用Sendmessage方法实现Unity不同进程之间通信。

核心代码

using System;

using System.Collections;

using System.Collections.Generic;

using System.Runtime.InteropServices;

using System.Text;

using UnityEngine;


/// <summary>

/// 传递的数据结构

/// </summary>

public struct COPYDATASTRUCT

{

    public IntPtr dwData;

    public int cData;

    [MarshalAs(UnmanagedType.LPStr)]

    public string lpData;

}



/// <summary>

/// 收到消息的数据结构,里面包含COPYDATASTRUCT数据

/// </summary>

public struct CWPRETSTRUCT

{

    public IntPtr lparam;//指定的消息内容

    public IntPtr wparam;//消息内容

    public uint message;//消息类型

    public IntPtr hwnd;//发送消息的句柄

}


public class WindowsProcessCommunication

{

    //全局监听

    private const int WH_CALLWNDPROC = 4;

    private const int WM_COPYDATA = 0x004A;

    [DllImport("User32.dll")]

    public static extern IntPtr SendMessage(IntPtr hwnd, int msg, IntPtr wParam, ref COPYDATASTRUCT IParam);

    [DllImport("User32.dll")]

    public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);



    //设置一个监听

    [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, IntPtr wParam, IntPtr lParam);

    //委托

    private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);


    public delegate void ReciveMsgCallback(string msg);


    private static ReciveMsgCallback reciveMsgCallback;

    static int hookID = 0;

    

    private static IntPtr myWindows;



    /// <summary>

    /// 目标窗体的进程名称

    /// </summary>

    /// <param name="msgContent"></param>

    /// <param name="targetWindow"></param>

    public static void SendMessage(string msgContent, IntPtr targetWindow)

    {

        myWindows = FindWindow(null, Application.productName);



        String strSent = msgContent;



        if (targetWindow != IntPtr.Zero)

        {

            byte[] arr = System.Text.Encoding.Default.GetBytes(strSent);

            int len = arr.Length;

            COPYDATASTRUCT cdata;

            cdata.dwData = (IntPtr)100;

            cdata.lpData = strSent;

            cdata.cData = len + 1;

            SendMessage(targetWindow, WM_COPYDATA, myWindows, ref cdata);


            //Debug.LogError(msgContent);

        }


    }

    public static void HookLoad(ReciveMsgCallback rmsg)

    {

        reciveMsgCallback = rmsg;

        Debug.LogError("绑定回调");



        HookProc lpfn = new HookProc(Hook);


        IntPtr hInstance = IntPtr.Zero;

        hookID = SetWindowsHookEx(WH_CALLWNDPROC, lpfn, hInstance, (uint)AppDomain.GetCurrentThreadId());


        if (hookID<0) { 

            UnhookWindowsHookEx(hookID);


        }

        


    }



    //卸载钩子

    public static void UnhookWindowsHookEx()

    {

        if (hookID>0)

        {

            UnhookWindowsHookEx(hookID);

        }

    }


    private static unsafe int Hook(int nCode, IntPtr wParam, IntPtr lParam)

    {

        try

        {

            CWPRETSTRUCT m = (CWPRETSTRUCT)Marshal.PtrToStructure(lParam, typeof(CWPRETSTRUCT));

            if (m.message == WM_COPYDATA)

            {

                COPYDATASTRUCT cdata = (COPYDATASTRUCT)Marshal.PtrToStructure(m.lparam, typeof(COPYDATASTRUCT));


                reciveMsgCallback?.Invoke(cdata.lpData);


            }

            return CallNextHookEx(hookID, nCode, wParam, lParam);


        }

        catch (Exception ex)

        {

            Debug.LogError(ex.Message);

            return 0;

        }

    }

}


调用代码

using System.Collections;

using System.Collections.Generic;

using UnityEngine;


using UnityEngine.UI;


public class NewBehaviourScript : MonoBehaviour

{


    public InputField receviceInputField;

    public InputField msgInputField;


    public Text receiveMsgText;


    public Button sendMsg;


    private void Start()

    {

        sendMsg.onClick.AddListener(() =>

        {

            if (!string.IsNullOrEmpty(msgInputField.text)) {

               

                WindowsProcessCommunication.SendMessage(msgInputField.text, WindowsProcessCommunication.FindWindow(null, receviceInputField.text));

            }

        });

        WindowsProcessCommunication.HookLoad(ReciveMsgCallback);

    }


    public void ReciveMsgCallback(string msg) {

        Debug.LogError("收到消息:" + msg);


        receiveMsgText.text ="收到消息:"+ msg;



    }


    private void OnDestroy()

    {

        WindowsProcessCommunication.UnhookWindowsHookEx();

    }


}

工程地址:https://github.com/994935108/WindowsProcessCommunication.git


在Windows平台上。使用Sendmessage方法实现Unity不同进程之间通信的评论 (共 条)

分享到微博请遵守国家法律