C#跟Python用WM_COPYDATA通讯

本文介绍了如何使用Python和C#通过WM_COPYDATA机制实现实时进程间通信,包括接收端的Listener类和发送端的 SendMessage 函数,展示了如何通过类名或窗口名定位目标窗口并发送消息。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考了两篇文章,写得很好。感谢。
python https://blog.csdn.net/ndd1996/article/details/107882856
C# https://blog.csdn.net/liang08114/article/details/108644659

# -*- codeing = utf-8 -*-
# @Time : 2022/5/17 11:30
# @Author: CXZ
# @Flie : received.py
# @Software: PyCharm

import threading
import time

import ctypes
import ctypes.wintypes
import win32api
import win32con
import win32gui


class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [
        ('dwData', ctypes.wintypes.LPARAM),
        ('cbData', ctypes.wintypes.DWORD),
        ('lpData', ctypes.c_void_p)
    ]


PCOPYDATASTRUCT = ctypes.POINTER(COPYDATASTRUCT)


class EndOfTime(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        while 1:
            print(1)
            time.sleep(3)


class Listener:
    def __init__(self):
        WindowName ="CopyDataName" #class name
        message_map = {
            win32con.WM_COPYDATA: self.OnCopyData
        }
        wc = win32gui.WNDCLASS()
        wc.lpfnWndProc = message_map
        wc.lpszClassName = WindowName
        hinst = wc.hInstance = win32api.GetModuleHandle(None)
        classAtom = win32gui.RegisterClass(wc) #把上面的class name 等相关参数注册 再传入到下面的CreateWindow
        self.hwnd = win32gui.CreateWindow( #这里是python 创建窗体用的
            classAtom,
            "WMSGReceiver1", #这个是窗体name
            0,
            0,
            0,
            win32con.CW_USEDEFAULT,
            win32con.CW_USEDEFAULT,
            0,
            0,
            hinst,
            None
        )
        print("当前句柄", self.hwnd)

    def OnCopyData(self, hwnd, msg, wparam, lparam):
        pCDS = ctypes.cast(lparam, PCOPYDATASTRUCT)
        s = ctypes.string_at(pCDS.contents.lpData).decode()
        print(f"收到来自句柄{hwnd}的消息:{s}")
        return 1


l = Listener()
win32gui.PumpMessages()


上面是接收端的python代码 直接可用 是上面参考python博客的基础上做些注脚

# -*- codeing = utf-8 -*-
# @Time : 2022/5/17 15:44
# @Author: CXZ
# @Flie : send.py
# @Software: PyCharm
import ctypes.wintypes

import win32con

FindWindow = ctypes.windll.user32.FindWindowW
SendMessage = ctypes.windll.user32.SendMessageW


class COPYDATASTRUCT(ctypes.Structure):
    _fields_ = [
        ('dwData', ctypes.wintypes.LPARAM),
        ('cbData', ctypes.wintypes.DWORD),
        ('lpData', ctypes.c_char_p)
    ]


# 通过寻找窗口名获取句柄
#hwnd = FindWindow('CopyDataName', None)
hwnd = FindWindow(None, 'WMSGReceiver')#第一个参数是class name  第二个是窗体应用name

# 或者直接根据句柄来发送
# hwnd = 1707560
cds = COPYDATASTRUCT()
cds.dwData = 0
msg = "22233311"
msg_bytes = msg.encode('utf-8')
cds.cbData = ctypes.sizeof(ctypes.create_string_buffer(msg_bytes))
cds.lpData = ctypes.c_char_p(msg_bytes)
SendMessage(hwnd, win32con.WM_COPYDATA, 0, ctypes.byref(cds))
print("已发送CopyData数据", msg)
print(hwnd)


发送端python代码

下面是C# 的代码 也是直接可以用 点击button1 会发送message 发送成功 label1会对应变成hello 发送失败变成hello2 看对应的代码很简单。 当其他程序发送信息过来,成功的话,就会在textbox上面显示。个人觉得整个过程中需要注意的地方是怎么找到对应的句柄。一个是通过classname 一个是通过windowsname 这个是窗体应用名字 如果是通过windowsname 那就会自顶层往下找,看有没有对得上号的窗体名。如果有填classname的信息 那优先是配对classname信息。

在这里插入图片描述

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices;


namespace WindowsFormsApp1
{

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        [DllImport("user32.dll", EntryPoint = "FindWindow")]
        private extern static IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("User32.dll")]
        public static extern int SendMessage(IntPtr hwnd, int msg, int wParam, ref COPYDATASTRUCT lParam);


        public const int WM_COPYDATA = 0x004A;

        string FormText = "WMSGReceiver1";
        //IntPtr hdl = FindWindow(null, FormText);
        IntPtr hdl = FindWindow("CopyDataName", null);




        private void button1_Click(object sender, EventArgs e)
        {
            //string ClassName = "WindowsForms10.Window.8.app.0.3ee13a2_r13_ad1";
           // string FormText = "WMSGReceiver1";
            //IntPtr hdl = FindWindow(null, FormText);
            //IntPtr hdl = FindWindow("CopyDataName",null);
            if (hdl != IntPtr.Zero)
            {
                string msg = "asdf";
                byte[] sarr = Encoding.Default.GetBytes(msg);
                COPYDATASTRUCT cds;
                cds.dwData = IntPtr.Zero;                                   //可以是任意值
                cds.cbData = sarr.Length + 1;                               //指定lpData内存区域的字节数
                cds.lpData = msg;                                           //发送给目标窗口所在进程的数据

                SendMessage(hdl, WM_COPYDATA, 0, ref cds);

                label1.Text = "hello";
                return;

            }
            label1.Text = "Hello2";
        }

        private void label1_Click(object sender, EventArgs e)
        {

        }


        #region Windows Form Designer generated code

        [STAThread]


        protected override void DefWndProc(ref

        System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                //接收自定义消息 USER,并显示其参数
                case WM_COPYDATA:
                    COPYDATASTRUCT mystr = new COPYDATASTRUCT();
                    Type mytype = mystr.GetType();

                    mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
                    this.textBox1.Text = mystr.lpData;
                    

                    break;
                default:
                    base.DefWndProc(ref m);
                    break;

            }

        }

        /// <summary>
        /// WM_COPYDATA消息,进程间传输信息专用结构
        /// </summary>
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;

            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;

        }

        private void textBox1_TextChanged(object sender, EventArgs e)
        {

        }



    }
}
#endregion```

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值