2017-06-14 113 views
-1

我有一个非常有名的使用(丑)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,并且发件人从SendMessage调用获得0结果。

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.StructToPtrSendMessage的最后一个参数类型为IntPtr,但不幸没有成功(相同的行为)。

我试图依靠CLR编组通过改变COPYDATASTRUCT定义:

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

    [MarshalAs(UnmanagedType.LPWStr)] 
    public string lpData; 
} 

你猜怎么着?没有效果。

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

+2

dwData是一个IntPtr(可变大小32或64),而不是32位值。它可能在32位上工作,但会在64位上失败。 lpData必须是一个IntPtr,而不是一个字符串。 https://stackoverflow.com/questions/6779731/c-sharp-using-sendmessage-problem-with-wm-copydata –

+0

在C#中复制甚至简单的C++结构可能会非常棘手;除了普通的P/Invoke之外,C++/CLI可能更好。 –

+0

@SimonMourier,似乎这个错误'dwData'类型是问题。如果你将它作为答案发布,我会接受它。 'lpData'可以是一个'string',但是,它只是需要适当编组('[MarshalAs(UnmanagedType.LPWStr)'')。 – dymanoid

回答

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字节)。由于这是该结构中的第一个字段,所以当其定义不正确时,所有投注都关闭。

相关问题