下面我将详细讲解“C#使用SendMessage实现进程间通信的方法”的完整攻略。本篇攻略包含以下几个部分:
- 介绍进程间通信的概念
- 介绍在C#中使用SendMessage实现进程间通信的方法
- 两个示例说明
进程间通信概念
进程间通信(Inter-process communication,IPC)指的是同一台计算机上的多个进程之间的通信。从某种意义上来说,进程间通信就是多个进程协同工作、相互合作的一种方式。
进程间通信有多种方法,包括共享内存、管道、套接字等。而本文将介绍使用SendMessage方法实现进程间通信的方法。
C#中使用SendMessage方法实现进程间通信
SendMessage是Windows API中的一个函数,它可以用来向指定的窗口发送消息。在C#中,可以使用DllImport特性来调用Windows API中的SendMessage函数。
使用SendMessage函数实现进程间通信的主要流程如下:
- 在发送方进程中使用FindWindow函数或FindWindowEx函数获取接收方进程中的窗口句柄。
- 将要发送的消息封装成一个结构体(通常包括消息类型、消息内容等信息)。
- 使用SendMessage函数向接收方进程中的窗口句柄发送消息。
- 在接收方进程中重写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技术站