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日

相关文章

  • VS2008中使用JavaScript调用WebServices

    VS2008中使用JavaScript调用WebServices的完整攻略 在VS2008中,我们可以使用JavaScript调用WebServices。本文将提供详细的“VS2008中使用JavaScript调用WebServices”的完整攻略,包括如何创建WebServices、如何使用JavaScript调用WebServices以及两个示例。 创建…

    C# 2023年5月15日
    00
  • 如何用C#验证IP是否为局域网地址

    首先,我们需要了解什么是IP地址和局域网地址。 IP地址是Internet Protocol Address的缩写,也就是网络协议地址的意思。它是用来标识网络上的设备的数字串,类似于人类的身份证号码。而局域网地址则是指在局域网内的设备所使用的地址范围。通常局域网地址以“192.168”或“10.”开头。 下面是使用C#语言验证IP地址是否为局域网地址的代码:…

    C# 2023年6月6日
    00
  • .NET通过字典给类赋值实现代码

    对于.NET Framework提供的某些类型,我们可以通过字典的方式给类对象中的属性赋值。下面是实现过程的完整攻略: 1. 引入命名空间 在使用字典给类赋值时,我们需要引入System.Reflection命名空间。在代码中添加以下语句即可: using System.Reflection; 2. 创建类对象 首先,我们需要创建类的对象,以便我们可以给类的…

    C# 2023年5月31日
    00
  • C#获取所有进程的方法

    关于C#获取所有进程的方法,我们可以通过以下步骤进行实现。 1. 引用命名空间 我们需要在代码中添加System.Diagnostics命名空间,代码如下: using System.Diagnostics; 2. 获取所有进程 我们使用Process类中的静态方法GetProcesses()获取当前运行的所有进程,代码如下: Process[] proce…

    C# 2023年6月6日
    00
  • 浅析依赖注入框架Autofac的使用

    浅析依赖注入框架Autofac的使用 什么是依赖注入 依赖注入(Dependency Injection,DI)是一种设计模式,它可以将组件的依赖关系设计清晰、易于维护、易于测试。依赖注入主要是通过构造函数、属性和接口注入的方式将组件依赖关系解耦。在DI中,组件不再关注如何获取依赖组件,而是将依赖的对象交由其他组件来注入。 Autofac框架简介 Autof…

    C# 2023年5月31日
    00
  • .net中的Span类和Memory类介绍

    .NET中的Span类和Memory类介绍 在.NET中,Span类和Memory类是用于处理内存的重要类型。本攻略将介绍这两个类的基本概念、用法和示例。 Span类 Span类是一个结构体,用于表示一段连续的内存区域。它可以用于读取和写入内存,而无需进行复制或分配。Span类的定义如下: public ref struct Span<T> { …

    C# 2023年5月17日
    00
  • ASP.NET Web页生命周期和执行的方法介绍

    ASP.NET Web页生命周期和执行的方法是指在ASP.NET应用程序中,对Web页面的创建、加载、执行和销毁等过程的描述。ASP.NET Web页的生命周期是按照一定的顺序,从初始化、预处理、控件事件处理、视图的渲染等一系列过程组成的。 下面,我们将对ASP.NET Web页的生命周期及其执行的方法进行详细的介绍: ASP.NET Web页的生命周期 A…

    C# 2023年6月3日
    00
  • C#流程控制详解

    C#流程控制详解 前言 C#中的流程控制结构对于程序设计师是非常重要的,它可以控制代码的执行次序和执行条件,使得程序可以更好的实现我们所期望的功能。本文将讲解C#中常见的流程控制结构,包括分支语句和循环语句,并对每种结构进行详细解释和举例。 分支语句 if语句 if语句是一种最基本的分支语句,用于判断某个条件是否成立,如果条件成立执行一定的代码块,如果条件不…

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