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日

相关文章

  • C#下listview如何插入图片

    关于C#下listview如何插入图片,以下是详细攻略。 1. 添加图片列 首先我们需要在listview中添加一列,这一列用于存储图片。 listView1.Columns.Add("图片列", 80); 其中,”图片列”是列标题,80是列的宽度。为了方便,我们这里设置列宽为80。 2. 添加图片到列表项 接下来,我们需要添加图片到列表…

    C# 2023年6月6日
    00
  • C# 使用Fluent API 创建自己的DSL(推荐)

    当我们需要处理某些特定的问题时,我们可以使用一种特定的编程语言或工具,这种语言或工具专门用于解决此类问题。但是在使用这种特定语言或工具的情况下,我们可能会受到限制,因为只能使用特定的语法和工具。因此,我们可以使用DSL(Domain Specific Language,领域特定语言)来解决这个问题。DSL是一种针对特定领域的编程语言,可以让我们在这个领域内拥…

    C# 2023年6月7日
    00
  • 一篇文章带你轻松了解C# Lock关键字

    一篇文章带你轻松了解C# Lock关键字 Lock关键字是什么 Lock是C#编程中非常重要的一个关键字,主要用来进行多线程编程时的同步控制。在多线程程序中,不同的线程会同时对同一数据进行访问,如果没有同步控制,则有可能发生数据竞争的问题。使用Lock关键字可以保证在同一时间只有一个线程对共享资源进行访问。 Lock关键字的用法 Lock关键字用法非常简单,…

    C# 2023年5月15日
    00
  • ASP.NET MVC4入门教程(三):添加一个视图

    让我来详细讲解一下“ASP.NET MVC4入门教程(三):添加一个视图”的完整攻略。 1. 为什么要添加视图 首先,需要理解什么是ASP.NET MVC4中的视图。视图是MVC模式中的“V”(即View)。一般来说,控制器从模型中获取数据并进行逻辑处理,然后将处理后的结果传递给视图,视图负责将数据渲染成HTML页面,最终呈现给用户。 由于视图是MVC模式中…

    C# 2023年5月31日
    00
  • C#中使用Spire.XLS来操作Excel数据的实现

    让我来详细讲解一下“C#中使用Spire.XLS来操作Excel数据的实现”的完整攻略。 一、Spire.XLS简介 Spire.XLS是一个功能强大的.NET组件,能够帮助C#开发者快速创建、读取、修改和保存Microsoft Excel文件。它支持Excel文件的多个版本,包括Excel 97-2003、Excel 2007-2010和Excel 201…

    C# 2023年6月7日
    00
  • .net任务调度框架Hangfire简介

    .NET任务调度框架Hangfire简介 Hangfire是一个.NET任务调度框架,它可以帮助我们在.NET应用程序中轻松地执行后台任务。Hangfire提供了一个简单的API,可以让我们创建和管理后台任务,例如发送电子邮件、生成报告、处理队列等。Hangfire还提供了一个可视化仪表板,可以让我们轻松地监视和管理后台任务。 安装Hangfire 我们可以…

    C# 2023年5月17日
    00
  • .Net Framework .Net  .NET Standard的概念及区别

    让我为你详细讲解一下 “.Net Framework”、”.Net Core”、”.NET Standard” 这三个概念及它们之间的区别。 .Net Framework .NET Framework 是一个由 Microsoft 开发的用于创建 Windows 应用程序的平台,它提供了一个环境,让程序员可以轻松地编写 Windows 应用程序并且不必考虑平…

    C# 2023年6月3日
    00
  • .NET使用.NET Core CLI开发应用程序

    .NET使用.NET Core CLI开发应用程序攻略 在本攻略中,我们将详细介绍如何使用.NET Core CLI开发应用程序。我们将会涵盖以下内容: 安装.NET Core SDK 创建.NET Core应用程序 编写代码 构建和运行应用程序 示例说明 1. 安装.NET Core SDK 在开始之前,您需要安装.NET Core SDK。您可以从官方网…

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