为什么在提供数据有效负载时没有收到WM_COPYDATA消息?

时间:2017-06-14 15:17:28

标签: c# winforms pinvoke windows-messages wm-copydata

我使用(丑陋的)WM_COPYDATA消息为进程间数据交换提供了一个非常着名的设置。这不是我的决定,我必须在传统应用中支持它。

const uint WM_COPYDATA = 0x004A;

[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
  public uint dwData;
  public int cbData;
  public IntPtr lpData;
}

[DllImport("user32.dll")]
static extern int SendMessage(IntPtr hwnd, uint msg, IntPtr wparam, ref COPYDATASTRUCT lparam);

如果我只发送一个简单的结构,而不附加其他数据,它就可以正常工作:

COPYDATASTRUCT container;
container.dwData = 42;
container.cbData = 0;
container.lpData = IntPtr.Zero;
SendMessage(myHwnd, WM_COPYDATA, IntPtr.Zero, ref container);

在接收方(外部WinForms应用程序)上,我收到此消息并可以正确阅读dwData字段:

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_COPYDATA)
    {
        var container = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
        MessageBox.Show(container.dwData.ToString()); // 42
    }
    base.WndProc(ref m);
}

但是,只要附加一些额外的有效负载,外部应用程序就会停止接收此消息。接收方窗口过程中m.Msg == WM_COPYDATA条件始终为false,发件人从0调用中获得SendMessage结果。

COPYDATASTRUCT container;
container.dwData = 42;
container.cbData = 4;
container.lpData = Marshal.AllocHGlobal(4);
int result = SendMessage(hwnd, WM_COPYDATA, IntPtr.Zero, ref container); // 0

(实际上,这是一个虚拟有效载荷,但与真实有效载荷相同。)

string payload = "test";
container.cbData = (payload.Length + 1) * 2;
container.lpData = Marshal.StringToHGlobalUni(payload);

我还试图通过将COPYDATASTRUCT的最后一个参数类型更改为Marshal.StructToPtr来手动整理SendMessage IntPtr,但遗憾的是没有成功(相同的行为)。

我试图通过更改COPYDATASTRUCT定义来依赖CLR编组:

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct COPYDATASTRUCT
{
  public uint dwData;
  public int cbData;

  [MarshalAs(UnmanagedType.LPWStr)]
  public string lpData;
}
猜猜是什么?没效果。

我的设置有什么问题?当有效负载附加到数据结构时,为什么无法接收消息?

1 个答案:

答案 0 :(得分:2)

结构定义不正确,应该是

[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
  public IntPtr dwData; // in C/C++ this is an UINT_PTR, not an UINT
  public int cbData;
  public IntPtr lpData;
}

您对dwData的定义在32位进程(4字节)中匹配正常,但在64位进程(8字节)中则不匹配。由于这是结构中的第一个字段,所以当它的定义不正确时,所有的赌注都会被关闭。