来自.NET的WinAPI SendMessage

时间:2012-05-20 21:45:17

标签: pinvoke sendmessage

我有一个winapi代码示例:

struct CommunicationInfo {
    long internalMsg;
    const TCHAR * srcModuleName;
    void * info; 
  };

...

const TCHAR* szText = _T("Hello from my plugin!\n(test message)");
    CommunicationInfo ci = { 0x0401, cszMyPlugin, (void *) szText };
    ::SendMessage( hNppWnd, 0x111, (WPARAM) _T("NppExec.dll"), (LPARAM) &ci );

我想从.net拨打同一个电话,我写了这样的包装:

[StructLayout(LayoutKind.Sequential)]
    public struct CommunicationInfo
    {
        public Int64 internalMsg;
        [MarshalAs(UnmanagedType.LPWStr)]
        public StringBuilder srcModuleName;
        [MarshalAs(UnmanagedType.LPWStr)]
        public StringBuilder data;
    };

...

[DllImport("user32")]
public static extern IntPtr SendMessage(IntPtr hWnd, 
    NppMsg Msg, IntPtr wParam, 
    [MarshalAs(UnmanagedType.Struct)] CommunicationInfo communicationInfo);

...

SendMessage(hNppWnd, 0x111, 
    Marshal.StringToHGlobalUni("NppExec.dll"), 
    new CommunicationInfo 
    { 
        data = new StringBuilder("test test"),
        internalMsg = 0x0401,
        srcModuleName = new StringBuilder("ModuleName")
    });

但是这段代码不起作用。我在哪里弄错了?

2 个答案:

答案 0 :(得分:3)

我相信,CommunicationInfo结构中的字段在WinAPI中是32位的。因此,尝试在C#

中将“internalMsg”定义为System.Int32

可以肯定的是,尝试在C / C ++中调用printf(“%d \ n”,sizeof(CommunicationInfo))来了解实际大小。如果在32位系统上为(4 + 4 + 4),那么C#结构也必须是12字节大小。

“char *”指针也必须是指向非托管内存的指针,因此StringBuilder不会这样做。

有关编组示例

,请参阅此PInvoke error when marshalling struct with a string in it

答案 1 :(得分:1)

正如Viktor所指出的,C / C ++ long的大小为32位,因此需要与C#int匹配。最重要的是,没有正确处理结构的传递。此外,由于您从未致电StringToHGlobalUni,因此对FreeHGlobal的呼叫会泄漏。

我可能会处理这样的编组:

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CommunicationInfo
{
    public int internalMsg;
    public string srcModuleName;
    public string data;
};
....
[DllImport("user32")]
public static extern IntPtr SendMessage(
    IntPtr hWnd, 
    uint Msg, 
    [MarshalAs(UnmanagedType.LPWStr)] string wParam, 
    ref CommunicationInfo communicationInfo
);
....
CommunicationInfo communicationInfo = new CommunicationInfo 
{ 
    internalMsg = 0x0401,
    srcModuleName = "ModuleName",
    data = "test test"
};
SendMessage(hNppWnd, 0x111, "NppExec.dll", ref communicationInfo);