c# 通过 SendMessage 实现跨进程数据通信
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; namespace WindowsFormsApplication9 { public partial class Form1 : Form { const string hwndMapName = "MyMediaPlayerServiceHwnd"; const string messageResultMapName = "MyMediaPlayerServiceResult"; const int resultBufferSize = 1 * 1024 * 1024; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { // 创建或打开只读的内存映射文件 MemoryMappedFile memoryMappedFile = MemoryMappedFile.CreateOrOpen(hwndMapName, sizeof(int)); MemoryMappedViewAccessor accessor = memoryMappedFile.CreateViewAccessor(); int sharedInt = this.Handle.ToInt32(); // 要写入的int值 accessor.Write(0, ref sharedInt); } private void button1_Click(object sender, EventArgs e) { new Form2().ShowDialog(); } [StructLayout(LayoutKind.Sequential)] public struct COPYDATASTRUCT { public IntPtr dwData; // 用于指定消息类型 public int cbData; // 用于指定lpData指向的缓冲区的字节数 public IntPtr lpData; // 用于指向要发送数据的指针 } private const uint WM_COPYDATA = 0x004A; protected override void WndProc(ref Message m) { if (m.Msg == WM_COPYDATA) { var resultCode = 1; COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT)); if (cds.cbData > 0 && cds.lpData != IntPtr.Zero) { byte[] data = new byte[cds.cbData]; Marshal.Copy(cds.lpData, data, 0, cds.cbData); string receivedString = System.Text.Encoding.Unicode.GetString(data); using (MemoryMappedFile resultMappedFile = MemoryMappedFile.OpenExisting(messageResultMapName, MemoryMappedFileRights.ReadWrite)) { // 从内存映射文件中读取int值 using (MemoryMappedViewAccessor resultAccessor = resultMappedFile.CreateViewAccessor()) { var message = "Hi Sender!"; var result = Encoding.UTF8.GetBytes(message); if (result.Length > resultBufferSize) resultCode = 0; else resultAccessor.WriteArray(0, result, 0, result.Length); } } } m.Result = new IntPtr(resultCode); return; } base.WndProc(ref m); } } }
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Runtime.InteropServices; using System.IO.MemoryMappedFiles; namespace WindowsFormsApplication9 { public partial class Form2 : Form { const string hwndMapName = "MyMediaPlayerServiceHwnd"; const string messageResultMapName = "MyMediaPlayerServiceResult"; const int resultBufferSize = 1 * 1024 * 1024; [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, ref COPYDATASTRUCT cds); private const uint WM_COPYDATA = 0x004A; [StructLayout(LayoutKind.Sequential)] private struct COPYDATASTRUCT { public IntPtr dwData; public int cbData; public IntPtr lpData; } public Form2() { InitializeComponent(); } private void Form2_Load(object sender, EventArgs e) { textBox1.Text = SendMessage("Hi, Reciever!"); } private string SendMessage(string message) { // 打开只读的内存映射文件,以读取目标窗口句柄 using (MemoryMappedFile hwndMappedFile = MemoryMappedFile.OpenExisting(hwndMapName, MemoryMappedFileRights.ReadWrite)) { // 从内存映射文件中读取int值 using (MemoryMappedViewAccessor hwndAccessor = hwndMappedFile.CreateViewAccessor()) { int sharedInt; hwndAccessor.Read(0, out sharedInt); var hwnd = new IntPtr(sharedInt); #region 向目标窗口发送消息 // 将字符串转换为字节数组 byte[] messageBytes = System.Text.Encoding.Unicode.GetBytes(message); // 分配内存并将字节数组复制到内存中 IntPtr messagePtr = Marshal.AllocCoTaskMem(messageBytes.Length); Marshal.Copy(messageBytes, 0, messagePtr, messageBytes.Length); try { // 构造 COPYDATASTRUCT 结构体,将字符串指针和长度传递给接收方 COPYDATASTRUCT cds = new COPYDATASTRUCT(); cds.dwData = IntPtr.Zero; cds.cbData = messageBytes.Length; cds.lpData = messagePtr; using (MemoryMappedFile resultMappedFile = MemoryMappedFile.CreateOrOpen(messageResultMapName, resultBufferSize, MemoryMappedFileAccess.ReadWrite)) { // 使用 SendMessage 发送自定义消息 var result = SendMessage(hwnd, WM_COPYDATA, IntPtr.Zero, ref cds); if (result.ToInt32() != 1) return null; // 创建一个内存映射视图 using (MemoryMappedViewAccessor accessor = resultMappedFile.CreateViewAccessor(0, resultBufferSize, MemoryMappedFileAccess.ReadWrite)) { // 创建一个字节数组来接收读取的数据 byte[] byteArray = new byte[resultBufferSize]; // 从内存映射文件中读取字节数组 accessor.ReadArray(0, byteArray, 0, resultBufferSize); // 将字节数组转换为字符串 string data = Encoding.UTF8.GetString(byteArray); // 去除末尾的 \0 字符 data = data.TrimEnd('\0'); return data; } } } finally { // 释放内存 Marshal.FreeCoTaskMem(messagePtr); } #endregion } } } } }
注意:不同权限的进程之间发消息是有限制的
桂棹兮兰桨,击空明兮溯流光。