在x64中从指针编组结构

时间:2015-01-20 12:44:55

标签: c# struct pinvoke marshalling

我有三个结构:

    [StructLayout(LayoutKind.Sequential)]
    internal struct COPYDATASTRUCT
    {
        public IntPtr dwData;       // Specifies data to be passed
        public int cbData;          // Specifies the data size in bytes
        public IntPtr lpData;       // Pointer to data to be passed
    }

    public struct SHELLTRAYDATA
    {
        public UInt32 dwUnknown;
        public UInt32 dwMessage;
        public NID_XX nid;
    }

    public struct NID_XX
    {
        public UInt32 cbSize;
        public IntPtr hWnd;
        public uint uID;
        public uint uFlags;
        public uint uCallbackMessage;
        public IntPtr hIcon;
    }

在我的WndProc中,我会执行以下操作:

      case WM_COPYDATA:
                {
                    COPYDATASTRUCT cp = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
                    if(cp.dwData == SH_TRAY_DATA)
                    {
                        var shellTrayData = (SHELLTRAYDATA)Marshal.PtrToStructure(cp.lpData,typeof(SHELLTRAYDATA));
                        HandleNotification(shellTrayData);
                    }
                }

当我的应用程序在x86上运行时,它可以正常工作。当我在x64上运行它时,我没有得到一个hIcon,而且hWnd无效。当我将应用程序定位到x86并在x64上运行时,它工作正常。我知道问题在于编组。我是否必须手动编组结构?需要帮助。我希望x64和x86都具有相同的结构

编辑:

非托管结构如下:

typedef struct tagCOPYDATASTRUCT 
{
    ULONG_PTR dwData;
    DWORD cbData;
    _Field_size_bytes_(cbData) PVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

// data sent by shell via Shell_NotifyIcon
typedef struct _SHELLTRAYDATA
{
    DWORD dwUnknown;
    DWORD dwMessage;
    NID_XX nid;
} *PSHELLTRAYDATA;

// sub structure common to all others


  typedef struct
  {
  DWORD cbSize;
  HWND hWnd;
  UINT uID;
  UINT uFlags;
  UINT uCallbackMessage;
  HICON hIcon;
  } NID_XX, *PNID_XX;
  typedef const NID_XX * PCNID_XX;

编辑: 结构的大小如下:

未管理:

  1. COPYDATASTRUCT:12(X86)和24(x64)
  2. SHELLTRAYDATA:32(X86)和48(X64)
  3. NID_XX:24(X86)和40(X64)
  4. 托管:

    1. COPYDATASTRUCT:12(X86)和24(x64)
    2. SHELLTRAYDATA:32(X86)和48(X64)
    3. NID_XX:24(X86)和40(X64)
    4. 双方都是一样的。

2 个答案:

答案 0 :(得分:1)

这些结构因不同的架构而异。 IntPtr值为32位宽,或64位宽,具体取决于架构。这对成员的规模有明显的影响,也许对协调的后果不太明显。

无论架构如何,都无法使用相同的结构。您需要了解这两个过程的架构。无论何时发送方和接收方都没有相同的架构,那么您就遇到了麻烦。

您可以使用C#long代替IntPtr选择固定布局。 HWNDHICON等类型始终适合C#long。虽然要注意只在特定过程中有意义的句柄类型。例如,一旦将HICON值发送到其他进程,WM_COPYDATA值就没有意义。

我认为我会序列化,而不是使用固定的布局结构。例如,序列化您要发送给JSON的数据。这可以很容易地打包成一个字符串并通过{{1}}发送。

答案 1 :(得分:0)

由于Handles在64位构建上是64位,而我们接收的结构仍然包含32位。为hIcon和hWnd将IntPtr更改为Uint32就可以了。现在这个结构适用于x64和x86架构。我一直都知道JSON的序列化肯定会偏离我的要求。感谢您的帮助。