c#进程之间进行通信
【界面】
【代码】
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 进程通信
{
public partial class Form1 : Form
{
const int WM_COPYDATA = 0x004A;
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}
[DllImport("User32.dll")]
public static extern int SendMessage(int hwnd, int msg, int wParam, ref COPYDATASTRUCT lParam);
[DllImport("User32.dll")]
public static extern int FindWindow(string lpClassName, string lpWindowName);
public Form1()
{
InitializeComponent();
}
//发送消息
public bool sendmessageto(string windowname, string data)
{
int WINDOW_HANDLE = FindWindow(null, windowname);
if (WINDOW_HANDLE != 0)
{
byte[] arr = System.Text.Encoding.Default.GetBytes(data);
int len = arr.Length;
COPYDATASTRUCT cdata;
cdata.dwData = (IntPtr)100;
cdata.lpData = data;
cdata.cData = len + 1;
SendMessage(WINDOW_HANDLE, WM_COPYDATA, 0, ref cdata);
return true;
}
else
return false;
}
//接收消息
protected override void DefWndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
COPYDATASTRUCT cdata = new COPYDATASTRUCT();
Type mytype = cdata.GetType();
cdata = (COPYDATASTRUCT)m.GetLParam(mytype);
this.label1.Text = cdata.lpData;
break;
default:
base.DefWndProc(ref m);
break;
}
}
private void send_Click(object sender, EventArgs e)
{
sendmessageto(this.Windowname.Text, this.Message.Text);
}
}
}
【分析】
Windows消息系统由3部分组成:
1.消息队列。Windows应用程序的消息是由Windows统一在一个消息队列中管理的。
2.消息循环。应用程序从Windows消息队列中获得自己的消息,并将其分配给窗体函数进行处理。
3.窗口过程。负责处理接收到的消息,每个窗口都有对应的窗口过程,负责截获消息并响应。WndProc是窗口过程函数,负责处理接收到的消息,在我们写代码时,不会注意到有这个函数,这是因为开发环境自动为我们生成了。WndProc函数通过switch…case…判断并处理消息,对于在case中没有遇到的情况,会调用DefWndProc函数进行处理,所以,在C#中用户自定义消息,可以重载DefWndProc函数使用switch…case…判断并处理。
C#中的事件就是对Windows消息的封装,窗口过程中定义了窗体的事件,一定程度就是为了让程序员避免过多的考虑消息等底层的东西,所以能避免消息机制解决的问题最好能避免。
WM_COPYDATA 消息
该消息只能由 SendMessage() 发送 ,SendMessage()需要知道进程句柄,所以一般都搭配FindWindow()使用。通过FindWindow查找进程句柄,然后使用SendMessage() 向这个句柄发送信息
SendMessage函数
该函数将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口程序,直到窗口程序处理完消息再返回。而和函数PostMessage不同,PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam)
参数
hWnd:指定要接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口、被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
Msg:指定被发送的消息。
wParam:指定附加的消息特定信息。
IParam:指定附加的消息特定信息。
返回值:返回值指定消息处理的结果,依赖于所发送的消息。