我试图让2个应用程序使用Windows消息相互通信。 但是,在分配内存和数据封送期间,我一直在获取AccessViolationException(尝试读取或写入受保护的内存)。
有人可以向我解释什么是错的或建议更好的方法吗? 谢谢。
编辑:建议使用WM_COPYDATA,但现在我有另一个问题 - 另一个应用程序没有收到WM_COPYDATA消息。怎么了?
发送消息的代码:
public const int WM_COPYDATA = 0x004A;
public struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
public DATA lpData;
}
public struct DATA
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst=50)]
public char[] msg1;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=50)]
public char[] msg2;
}
[DllImport("User32.dll")]
public static extern int SendMessage(int hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
private void button1_Click(object sender, EventArgs e)
{
// data, with null terminated strings
COPYDATASTRUCT cds = new COPYDATASTRUCT();
cds.lpData.msg1 = textBox2.Text.PadRight(50, '\0').ToCharArray();
cds.lpData.msg2 = textBox3.Text.PadRight(50, '\0').ToCharArray();
cds.cbData = Marshal.SizeOf(cds.lpData);
int result = SendMessage(hwnd, WM_COPYDATA, System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle, ref cds); // winAPI
}
接收消息的代码(在另一个应用中):
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_COPYDATA)
{
// doesn't get into this part
COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
....
}
base.WndProc(ref m);
}
答案 0 :(得分:2)
Windows(和其他现代操作系统)中的指针是与进程相关的。您正在发送指向源进程的虚拟内存中的地址的指针。在目标进程中,可能无法映射此相同的虚拟内存位置,如果映射,则将完全不同。
要在进程之间复制数据,请使用WM_COPYDATA消息和Windows操作系统COPYDATASTRUCT。操作系统提供了这些特殊处理:它在进程之间复制引用的数据,并为目标进程提供指向目标进程内存空间中复制数据的指针。
此外,您的Marshal.StructureToPtr调用看起来不对。你的struct包含两个指针(因为char []是一个引用类型),所以你要将两个指针复制到你的HGLOBAL中,而不是字节数组的内容。您可以使用MarshalAsAttribute(UnmanagedType.ByValArray)来解决此问题,但在这种情况下您需要添加大小调整信息。一个更简单的解决方案可能是使用Marshal.Copy方法将数组复制到非托管内存中。
最后,如果您控制两个应用程序并且可以使用.NET 3.0或更高版本,请考虑托管WCF服务并以这种方式发送数据。您可能会发现这比使用Windows消息更容易,因为它将为您处理数据的序列化和反序列化 - 但我意识到这可能不是您的选择,或者您可能已经排除了它。
答案 1 :(得分:0)
您需要发送WM_COPYDATA
消息。
请参阅this thread。
答案 2 :(得分:0)
回答您编辑过的问题:
你确定你有合适的HWND吗?
使用Spy ++确保HWND正确,并检查Spy ++是否看到该消息。
确保您已在两个应用中正确定义WM_COPYDATA
常量。