我正在为我的组织编写一个新工具,它必须通过SendMessage与传统工具进行对话。
我刚刚使用此处的代码创建了一个测试应用: http://www.c-sharpcorner.com/Blogs/6444/
我编辑了发送代码以符合我的目的。但是我在“GetMessage”表单中接收消息时遇到了一些问题。消息确实通过但是在尝试将数据转换为字符串时程序会中断。
这是我的代码:
发送:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, ref COPYDATASTRUCT lParam);
[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
private void button1_Click(object sender, EventArgs e)
{
IntPtr hwnd = FindWindow(null, "GetMessage");
if (hwnd != null)
{
string message = textBox1.Text + "-" + System.DateTime.Now.ToString();
COPYDATASTRUCT cds;
cds.dwData = 0;
cds.lpData = (int)Marshal.StringToHGlobalAnsi(message);
cds.cbData = message.Length;
SendMessage(hwnd, (int)WM_COPYDATA, 0, ref cds);
}
}
收到:
private const int WM_COPYDATA = 0x4A;
[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
public int dwData;
public int cbData;
public int lpData;
}
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
COPYDATASTRUCT CD = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
byte[] B = new byte[CD.cbData];
IntPtr lpData = new IntPtr(CD.lpData);
//string test = Marshal.PtrToStringAuto(lpData, CD.lpData); // this doesn't work either
Marshal.Copy(lpData, B, 0, CD.cbData); // access violation here
string strData = Encoding.Default.GetString(B);
listBox1.Items.Add(strData);
break;
default:
base.WndProc(ref m);
break;
}
}
我得到的错误:
尝试读取或写入受保护的内存。这通常是一个 表明其他内存已损坏。
我已经尝试将发送中的消息字符串设置为字段(因此它不会超出范围),将发送消息的“int wParam”参数设置为“IntPtr”并使用IntPtr.Zero而不是我的SendMessage调用中为0,null终止字符串,如下所示:
cds.lpData = (int)Marshal.StringToHGlobalAnsi(message + '\0');
cds.cbData = (message+'\0').Length;
仍然遇到同样的问题。
答案 0 :(得分:0)
我解决了这个问题,我认为问题在于我使用的是int而不是IntPtr用于我的SendMessage和COPYDATASTRUCT。
我从http://pinvoke.net/default.aspx/user32.SendMessage和http://pinvoke.net/default.aspx/Structures/COPYDATASTRUCT.html
获得了这些信息这是工作代码:
private const int WM_COPYDATA = 0x004A;
[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
public IntPtr lpData;
}
发送:
[DllImport("user32.dll", CharSet = CharSet.Auto)]
//static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); // original
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref COPYDATASTRUCT cds); // override
private void SendMsg()
{
if (_hwnd != null)
{
COPYDATASTRUCT cds;
cds.dwData = IntPtr.Zero;
cds.lpData = Marshal.StringToHGlobalAnsi(stockCode);
cds.cbData = stockCode.Length;
SendMessage(_hwnd, (int) WM_COPYDATA, IntPtr.Zero, ref cds);
}
}
收到:
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_COPYDATA:
COPYDATASTRUCT CD = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
byte[] B = new byte[CD.cbData];
IntPtr lpData = CD.lpData;
Marshal.Copy(lpData, B, 0, CD.cbData);
string strData = Encoding.Default.GetString(B);
listBox1.Items.Add(strData);
break;
default:
base.WndProc(ref m);
break;
}
}
我相信这是在64位窗口上工作。