public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public const int WM_COPYDATA = 0x004A;
[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[StructLayout(LayoutKind.Sequential)]
public struct CopyDataStruct
{
public IntPtr dwData; // 附加参数
public int cbData; // 数据大小
public IntPtr lpData; // 数据内容
}
[DllImport("user32.dll")]
public static extern bool SendMessage(
IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
private void button1_Click(object sender, EventArgs e)
{
string S = textBox1.Text;
if (S.Length <= 0)
{
Console.WriteLine("内容为空");
return;
}
string processName = "WMCopyDataB";
Process[] vProcesses = Process.GetProcessesByName(processName); // 查询目标进程
if (vProcesses.Length <= 0)
vProcesses = Process.GetProcessesByName(processName + ".vshost"); // 处理调试运行
if (vProcesses.Length <= 0)
{
MessageBox.Show("目标进程没有找到");
return;
}
////string strDlgTitle = "processRecv";
//string strDlgTitle = "WMCopyDataB";
////接收端的窗口句柄
//IntPtr hwndRecvWindow = FindWindow(null, strDlgTitle);
//if (hwndRecvWindow == IntPtr.Zero)
//{
// MessageBox.Show("请先启动接收消息程序");
// return;
//}
CopyDataStruct vCopyDataStruct = new CopyDataStruct();
vCopyDataStruct.dwData = (IntPtr)0;
vCopyDataStruct.cbData = S.Length * sizeof(char) + sizeof(char); // 最后结束字符\x00
Debug.WriteLine(vCopyDataStruct.cbData);
vCopyDataStruct.lpData = Marshal.StringToBSTR(S);
IntPtr vAddress = Marshal.AllocCoTaskMem(Marshal.SizeOf(vCopyDataStruct));
Marshal.StructureToPtr(vCopyDataStruct, vAddress, true);
foreach (Process vProcess in vProcesses)
{
SendMessage(vProcess.MainWindowHandle, WM_COPYDATA, 0, vAddress); // 发送结构
}
Marshal.FreeBSTR(vCopyDataStruct.lpData);
Marshal.FreeCoTaskMem(vAddress);
}
}
接收端:
public partial class Form1 : Form
{
[DllImport("User32.dll")]
public static extern bool ChangeWindowMessageFilter(uint msg, int flags);
public Form1()
{
InitializeComponent();
//ChangeWindowMessageFilter(WM_COPYDATA, 1);
}
private void Form1_Load(object sender, EventArgs e)
{
ChangeWindowMessageFilter(WM_COPYDATA, 1); //**注册WM_COPYDATA消息,避免在win7中以管理员方式运行,过滤掉该消息。
}
[StructLayout(LayoutKind.Sequential)]
public struct CopyDataStruct
{
public IntPtr dwData; // 附加参数
public int cbData; // 数据大小
public IntPtr lpData; // 数据内容
}
public const int WM_COPYDATA = 0x004A;
protected override void DefWndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
CopyDataStruct vCopyDataStruct = (CopyDataStruct)Marshal.PtrToStructure(
m.LParam, typeof(CopyDataStruct));
string S = Marshal.PtrToStringBSTR(vCopyDataStruct.lpData);
textBox1.Text = S;
break;
}
base.DefWndProc(ref m);
}
}
有问题,不能正常接收,问题出在哪啊?
6 个解决方案
#1
这个主要还是自己调试.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.
#2
长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。
#3
问题是出在接收端“CopyDataStruct vCopyDataStruct = (CopyDataStruct)Marshal.PtrToStructure(
m.LParam, typeof(CopyDataStruct));” Out of Memory,但是我不知道为什么会出现这样的问题。
#4
后面三种听说过,没用过,这种最简单,哈哈哈。
#5
用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):
当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。
BSTR指针
|
v
05 00 00 00 'h' 'e' 'l' 'l' 'o' 00
当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。
#6
原来是这样,我换成其它方式确实可以了。
#1
这个主要还是自己调试.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.
1, sendmessage 和 postmessage.
2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.
#2
长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。
#3
问题是出在接收端“CopyDataStruct vCopyDataStruct = (CopyDataStruct)Marshal.PtrToStructure(
m.LParam, typeof(CopyDataStruct));” Out of Memory,但是我不知道为什么会出现这样的问题。
#4
后面三种听说过,没用过,这种最简单,哈哈哈。
#5
用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):
当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。
BSTR指针
|
v
05 00 00 00 'h' 'e' 'l' 'l' 'o' 00
当WM_COPYDATA帮你把数据(BSTR指针指向的数据)拷贝到其他进程时,只会拷贝'hello\0',并不会把前置长度05 00 00 00拷贝过去。
当目标进程还原BSTR时,‘'hello\0'前面可以是任意的垃圾,比如长度变成789272521等。这可能导致你内存溢出或非法访问。
#6
原来是这样,我换成其它方式确实可以了。