C#使用SendMessage实现进程间通信的方法

下面我将详细讲解“C#使用SendMessage实现进程间通信的方法”的完整攻略。本篇攻略包含以下几个部分:

  1. 介绍进程间通信的概念
  2. 介绍在C#中使用SendMessage实现进程间通信的方法
  3. 两个示例说明

进程间通信概念

进程间通信(Inter-process communication,IPC)指的是同一台计算机上的多个进程之间的通信。从某种意义上来说,进程间通信就是多个进程协同工作、相互合作的一种方式。

进程间通信有多种方法,包括共享内存、管道、套接字等。而本文将介绍使用SendMessage方法实现进程间通信的方法。

C#中使用SendMessage方法实现进程间通信

SendMessage是Windows API中的一个函数,它可以用来向指定的窗口发送消息。在C#中,可以使用DllImport特性来调用Windows API中的SendMessage函数。

使用SendMessage函数实现进程间通信的主要流程如下:

  1. 在发送方进程中使用FindWindow函数或FindWindowEx函数获取接收方进程中的窗口句柄。
  2. 将要发送的消息封装成一个结构体(通常包括消息类型、消息内容等信息)。
  3. 使用SendMessage函数向接收方进程中的窗口句柄发送消息。
  4. 在接收方进程中重写WndProc方法,以便能够接收到发送方发送的消息。在WndProc方法中,根据消息类型和内容来执行相应的逻辑。

下面是具体的代码示例。

发送进程代码示例

首先,我们要在发送进程中使用DllImport特性来引用Windows API中的SendMessage函数。具体代码如下:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

接下来,我们需要在发送进程中找到接收方进程中的窗口句柄。在本示例中,我们假设接收方进程中的窗口类名为“ReceiverWndClass”,窗口标题为“Receiver Window”:

IntPtr receiverHandle = FindWindow("ReceiverWndClass", "Receiver Window");

然后,我们需要将要发送的消息封装成一个结构体。在本示例中,我们定义了一个名为“SendMessageData”的结构体:

public struct SendMessageData
{
    public int MessageType;
    public string MessageContent;
}

最后,我们可以使用SendMessage函数将消息发送给接收方进程中的窗口:

SendMessage(receiverHandle, WM_COPYDATA, IntPtr.Zero, ref sendData);

接收进程代码示例

在接收进程中,我们需要重写WndProc方法,来接收发送方进程发送的消息。具体代码如下:

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_COPYDATA)
    {
        COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
        SendMessageData messageData = (SendMessageData)Marshal.PtrToStructure(cds.lpData, typeof(SendMessageData));

        // 根据消息类型和内容执行相应的逻辑
        if (messageData.MessageType == 1)
        {
            // 执行 A 操作
        }
        else if (messageData.MessageType == 2)
        {
            // 执行 B 操作
        }
        else
        {
            // 执行默认操作
        }
    }
    else
    {
        base.WndProc(ref m);
    }
}

在WndProc方法中,我们首先判断消息类型是否为WM_COPYDATA(COPYDATASTRUCT是用来封装WM_COPYDATA消息的结构体)。如果是,则从消息中提取出我们定义的SendMessageData结构体,并根据消息类型和内容执行相应的逻辑。

以上就是使用SendMessage实现进程间通信的完整攻略,下面将用两个示例来说明具体的使用方法。

示例1:在两个控制台程序之间传输数据

首先,我们要创建两个控制台程序,一个用于发送数据,一个用于接收数据。在发送数据的程序中,我们需要按照前面的说明,实现SendMessage函数和SendMessageData结构体。

发送程序的代码如下:

using System;
using System.Runtime.InteropServices;

namespace SenderConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            IntPtr receiverHandle = FindWindow(null, "Receiver Console");
            string messageContent = "Hello, Receiver!";
            SendMessageData sendData = new SendMessageData()
            {
                MessageType = 1,
                MessageContent = messageContent
            };
            IntPtr pSendData = Marshal.AllocHGlobal(Marshal.SizeOf(sendData));
            Marshal.StructureToPtr(sendData, pSendData, true);

            SendMessage(receiverHandle, WM_COPYDATA, IntPtr.Zero, pSendData);
            Console.WriteLine("Message sent: {0}", messageContent);

            Marshal.FreeHGlobal(pSendData);
            Console.ReadLine();
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

        public const uint WM_COPYDATA = 0x004A;

        public struct SendMessageData
        {
            public int MessageType;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string MessageContent;
        }
    }
}

在接收程序中,我们需要重写WndProc方法,来处理发送过来的消息。接收程序的代码如下:

using System;
using System.Runtime.InteropServices;

namespace ReceiverConsoleApp
{
    class Program
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

        public const uint WM_COPYDATA = 0x004A;

        public struct SendMessageData
        {
            public int MessageType;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string MessageContent;
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Receiver started.");
            Console.ReadLine();
        }

        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_COPYDATA)
            {
                COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(m.LParam, typeof(COPYDATASTRUCT));
                SendMessageData messageData = (SendMessageData)Marshal.PtrToStructure(cds.lpData, typeof(SendMessageData));

                Console.WriteLine("Message received: {0}", messageData.MessageContent);
            }
            else
            {
                base.WndProc(ref m);
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;
        }
    }
}

在接收程序中,我们重写WndProc方法,判断消息类型是否为WM_COPYDATA,在接收到WM_COPYDATA消息后,从消息中提取出SendMessageData结构体,并打印出消息内容。

现在我们运行发送程序和接收程序,如果一切正常,发送程序会发送一条消息给接收程序,并在控制台中输出“Message sent: Hello, Receiver!”;接收程序会接收到这条消息,并在控制台中输出“Message received: Hello, Receiver!”。

示例2:在Windows应用程序中向WPF应用程序发送消息

在这个示例中,我们将要创建一个Windows Forms应用程序和一个WPF应用程序,然后在Windows Forms应用程序中向WPF应用程序发送消息。

首先,我们要创建Windows Forms应用程序,并按照前面的说明实现SendMessage函数和SendMessageData结构体。我们还需要在该应用程序中添加一个Button控件,当用户点击该控件时,应用程序会向WPF应用程序发送一条消息。

Windows Forms应用程序的代码如下:

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace SenderWinFormsApp
{
    public partial class MainForm : Form
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

        public const uint WM_COPYDATA = 0x004A;

        public struct SendMessageData
        {
            public int MessageType;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string MessageContent;
        }

        public MainForm()
        {
            InitializeComponent();
        }

        private void SendButton_Click(object sender, EventArgs e)
        {
            IntPtr receiverHandle = FindWindow(null, "ReceiverWindow");
            string messageContent = "Hello, Receiver!";
            SendMessageData sendData = new SendMessageData()
            {
                MessageType = 1,
                MessageContent = messageContent
            };
            IntPtr pSendData = Marshal.AllocHGlobal(Marshal.SizeOf(sendData));
            Marshal.StructureToPtr(sendData, pSendData, true);

            SendMessage(receiverHandle, WM_COPYDATA, IntPtr.Zero, pSendData);

            Marshal.FreeHGlobal(pSendData);
        }
    }
}

接下来,我们要创建WPF应用程序,并在该应用程序中添加一个Window控件。我们还需要重写该控件的WndProc方法来处理发送过来的消息。

WPF应用程序的代码如下:

using System.Runtime.InteropServices;
using System.Windows;

namespace ReceiverWpfApp
{
    public partial class MainWindow : Window
    {
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);

        public const uint WM_COPYDATA = 0x004A;

        public struct SendMessageData
        {
            public int MessageType;
            [MarshalAs(UnmanagedType.LPWStr)]
            public string MessageContent;
        }

        public MainWindow()
        {
            InitializeComponent();
        }

        protected override void OnSourceInitialized(EventArgs e)
        {
            base.OnSourceInitialized(e);
            HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
            hwndSource.AddHook(new HwndSourceHook(WndProc));
        }

        private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            if (msg == WM_COPYDATA)
            {
                COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
                SendMessageData messageData = (SendMessageData)Marshal.PtrToStructure(cds.lpData, typeof(SendMessageData));

                MessageBox.Show(messageData.MessageContent);
            }

            return IntPtr.Zero;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;
        }
    }
}

在WPF应用程序中,我们首先重写了Window控件的OnSourceInitialized方法,以便获取窗口句柄。然后,我们重写了WndProc方法,判断消息类型是否为WM_COPYDATA,在接收到WM_COPYDATA消息后,从消息中提取出SendMessageData结构体,并在对话框中显示消息内容。

最后,我们将两个应用程序都运行起来。当用户在Windows Forms应用程序中点击按钮时,该程序会向WPF应用程序发送一条消息,并在WPF应用程序中弹出一个对话框,显示刚刚发送的消息。

这两个示例展示了如何使用SendMessage实现进程间通信,在实际开发中,还可以根据需要对代码进行进一步的优化和扩展。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#使用SendMessage实现进程间通信的方法 - Python技术站

(0)
上一篇 2023年6月7日
下一篇 2023年6月7日

相关文章

  • 关于若干数据库数据插入性能的对比分析

    关于若干数据库数据插入性能的对比分析 介绍 在数据库应用中,数据插入操作是最频繁的操作之一。因此,对于数据库性能的优化,数据插入性能的分析非常重要。本文将介绍若干数据库数据插入性能对比分析的攻略。 步骤 1. 选择数据集 首先需要选择一个数据集。数据集的大小和内容对于数据插入性能对比测试的结果会有很大的影响。因此,在选择数据集时应该在考虑数据大小、数据类型、…

    C# 2023年5月31日
    00
  • C#实现控制电脑注销,关机和重启

    以下是C#实现控制电脑注销、关机和重启的完整攻略: 1. 获取系统权限 为了能够控制电脑的操作,首先需要获取系统管理员权限。 可以使用以下代码获取管理员权限: ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.Verb = "runas"; startInfo.F…

    C# 2023年5月14日
    00
  • .NET 6 整合 Autofac 依赖注入容器

    前言 一行业务代码还没写,框架代码一大堆,不利于学习。常看到java的学习资料或博客,标题一般为《SpringBoot 整合 XXX》,所以仿照着写了《.NET 6 整合 Autofac 依赖注入容器》这样一个标题。以下是我自己的用法,可能不是最佳实践。 一. 引用包 NuGet搜索并安装:AutofacAutofac.Extensions.Dependen…

    C# 2023年5月3日
    00
  • C#中参数的传递方式详解

    下面是关于“C#中参数的传递方式详解”的完整攻略。 什么是参数传递? 方法是 C# 中的重要概念,而在方法中,参数的传递是很常见的操作。参数传递的方式可以决定方法对参数的作用,所以我们需要学习并理解这些方式。 C# 中的参数传递方式 C# 中参数传递的方式包括以下几种: 值类型参数传递 引用类型参数传递 输出参数传递 我们接下来逐一介绍这些方式。 值类型参数…

    C# 2023年5月15日
    00
  • 模拟人生4怎么复活死去的人物 复活死去人物的方法

    模拟人生4怎么复活死去的人物:完整攻略 在模拟人生4中,如果你的人物不幸“去世”,可以通过以下两种方法将他们复活: 方法一:使用“消费者保障” 在游戏中按下CTRL+Shift+C,弹出命令输入框,在其中输入testingcheats true,使得测试命令成为可用状态。 按下CTRL+Shift+C打开命令框,输入“cas.fulleditmode”(不带…

    C# 2023年6月6日
    00
  • C#遍历系统进程的方法

    C#遍历系统进程主要可以使用System.Diagnostics命名空间中的Process类实现。下面是具体步骤: 1.引入System.Diagnostics命名空间 using System.Diagnostics; 2.创建一个Process对象 Process process = new Process(); 3.设置Process对象的属性 pro…

    C# 2023年5月15日
    00
  • C#泛型集合类型实现添加和遍历

    下面是一份详细的攻略,分别讲解了C#泛型集合类型的添加和遍历。 添加元素到集合 List泛型列表 List 是 C# 中常见的泛型类型之一,其中的元素是可以重复的,可以方便的进行元素添加和删除操作。 //创建一个string类型的List泛型列表 List<string> list = new List<string>(); //使用…

    C# 2023年6月6日
    00
  • C#连接Informix数据库的问题

    使用C#连接Informix数据库的过程可以分为以下几个步骤: 步骤一:安装Informix客户端SDK Informix客户端SDK包括ODBC和 .NET 数据提供程序等。可以从IBM官网下载对应版本的SDK,安装并配置。 步骤二:创建Informix数据库连接字符串 在C#中,可以通过连接字符串来与Informix数据库建立连接。根据个人需要可以选择使…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部