进程间通信,使用WM_COPYDATA消息在两个程序间传递字符串,有问题。

Frog1228 2015-01-06 04:59:20
发送端:

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);
}
}

有问题,不能正常接收,问题出在哪啊?
...全文
176 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
Forty2 2015-01-07
  • 打赏
  • 举报
回复
用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):

          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等。这可能导致你内存溢出或非法访问。
Frog1228 2015-01-07
  • 打赏
  • 举报
回复
引用 5 楼 Forty2 的回复:
用BSTR是错的。因为BSTR指针指向的字符串前面有长度信息(就是那个05 00 00 00):

          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等。这可能导致你内存溢出或非法访问。
原来是这样,我换成其它方式确实可以了。
Frog1228 2015-01-06
  • 打赏
  • 举报
回复
引用 2 楼 lincolnandlinda 的回复:
长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。
后面三种听说过,没用过,这种最简单,哈哈哈。
Frog1228 2015-01-06
  • 打赏
  • 举报
回复
引用 1 楼 bambuz 的回复:
这个主要还是自己调试. 1, sendmessage 和 postmessage. 2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.
问题是出在接收端“CopyDataStruct vCopyDataStruct = (CopyDataStruct)Marshal.PtrToStructure( m.LParam, typeof(CopyDataStruct));” Out of Memory,但是我不知道为什么会出现这样的问题。
lincolnandlinda 2015-01-06
  • 打赏
  • 举报
回复
长见识了,从来没用过这种方式进行进程间通信。我一般使用共享内存、命名管理和Socket。
bambuz 2015-01-06
  • 打赏
  • 举报
回复
这个主要还是自己调试. 1, sendmessage 和 postmessage. 2. 能不能找到要接收消息的窗口; 接收端 是否能接受到消息; 消息中附带的数据能否正常解析.

110,502

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧