C# 从x64中的指针封送结构

C# 从x64中的指针封送结构,c#,struct,pinvoke,marshalling,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 IntPt

我有三个结构:

    [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;
编辑: 结构的大小如下所示:

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;
非托管:

  • COPYDATASTRUCT:12(X86)和24(x64)
  • 贝壳水母:32(X86)和48(X64)
  • NID_XX:24(X86)和40(X64)
  • 管理:

  • COPYDATASTRUCT:12(X86)和24(x64)
  • 贝壳水母:32(X86)和48(X64)
  • NID_XX:24(X86)和40(X64)

  • 两边都一样。

    这些结构在不同的体系结构上有所不同。
    IntPtr
    值为32位宽,或64位宽,具体取决于体系结构。这对成员国的规模有着明显的影响,而对联盟的影响可能不那么明显

    无论架构如何,都无法使用相同的结构。您需要了解这两个流程的体系结构。当发送方和接收方的体系结构不相同时,您就有麻烦了

    您可以选择一个固定的布局,使用C#
    long
    而不是
    IntPtr
    。像
    HWND
    HICON
    这样的类型总是适合C#
    long
    。尽管如此,还是要小心那些只在特定进程中有意义的句柄类型。例如,
    HICON
    值一旦发送到其他进程,就没有意义了


    我想我应该序列化,而不是使用固定的布局结构。例如,序列化要发送到JSON的数据。这可以很容易地打包成一个字符串,并通过
    WM_COPYDATA

    发送,因为在64位构建中句柄是64位的,而我们接收的结构仍然包含32位。将hIcon和hWnd的IntPtr更改为Uint32就成功了。现在,此结构可以在x64和x86体系结构上工作。我一直知道JSON的序列化肯定偏离了我的要求。感谢您的帮助。

    可以通过检查非托管结构定义找到答案。你没有介绍他们。这是互操作。互操作需要了解接口的双方。我们只能看到一面。1)您可能需要用32位整数替换一些
    IntPtr
    s,或者反过来。比较C和C中这些结构的定义,并使用中的表计算出正确的整数大小。2) 对齐差异是另一个潜在问题,但不应影响您的案例。我可以看到的另一个问题是,您可能有不同的体系结构。您正在使用
    WM\u COPYDATA
    对吗?是否有32位进程向64位进程发送消息?反之亦然?因为我的应用程序以“任何CPU”为目标,所以我的应用程序以64位进程运行,托盘图标为32位进程。我知道不同的体系结构,我在问题中也提到了同样的体系结构。但在这种情况下,我必须手动封送?如果是,怎么做?我看不出明显的不匹配。也许你在C++代码中使用了一个不寻常的打包。请确保C++代码中的结构的siZOFE()与你在C代码中得到的MSEHAL.siZOFE()完全匹配。请确保您不使用此功能在不同进程之间进行互操作。long Ding无助于我的原因。您必须到处更改结构。仅在C代码中更改它是不够的。您还需要更改非托管结构。非托管结构来自Win32项目,仅供我参考。在上面提到的所有3个结构中,我都将IntPtr改为long。如果我错了,请纠正我。您还需要更改非托管结构<代码>长为64位。在x86上,
    HWND
    HICON
    等为32位。你明白我在回答中写的吗?这是第一件要弄清楚的事。如果你只是改变代码而没有坚实的理解基础,你就不会成功。我确实理解了32位和64位的差异。我不明白的是,当我在.NET中P/调用非托管结构时,更改非托管结构会有什么帮助?我正在使用它的托管版本。你能用一个片段演示一下吗?我的托管结构是一个单独的应用程序。我的目的是在我自己的自定义外壳中获取托盘图标详细信息。