日期:2014-05-18  浏览次数:21058 次

64位中PRINT_NOTIFY_INFO_DATA这个Structure该怎么定义
昨天发了个贴没人理我,今天把问题再深入一些再发:)

先说明一下问题,PRINT_NOTIFY_INFO_DATA这个Structure在32位下OK,但是到了64位下获取到的东西是错误的,所以我觉得问题就出在这里了,下面是我目前的定义方法。

VB.NET code

<StructLayout(LayoutKind.Sequential)> _
    Private Class PrinterNotifyInfoData

        Public wType As Int16
        Public wField As Int16
        Public dwReserved As Int32
        Public dwId As Int32
        Public cbBuff As Int32
        Public pBuff As Int32

    End Class



请高人指点64位中的定义方法,C# VB都行,谢谢。

P.S.昨天贴的地址,没人回结贴都没法结。
http://topic.csdn.net/u/20120718/11/4031252f-3876-47eb-a8f7-b4676c8c641b.html

------解决方案--------------------
拿一段简单的C++代码测试了一下PRINTER_NOTIFY_INFO_DATA结构:

总的来说,为了内存对齐,在Id和cbBuf之后有一段内存是留空了。
可以考虑Id和cbBuf字段用IntPtr来保证对齐,而使用属性通过位运算来读取/设置这些值。
------解决方案--------------------
没有64位系统,没法测试,但你上面的定义肯定不对,字节对齐不是通过修改数据类型来实现的,那样做不出错的话,我叫他爷。C++里面默认是8字节对齐的,也就是#pragma pack (8),而C#里面也是,所以字节对齐是不会有不同的,除非C++里面有特殊指定。
------解决方案--------------------
C# code

typedef struct _PRINTER_NOTIFY_INFO_DATA { 
  WORD   Type; 
  WORD   Field; 
  DWORD  Reserved; 
  DWORD  Id; 
  union { 
      DWORD  adwData[2]; 
      struct { 
          DWORD  cbBuf; 
          LPVOID pBuf; 
      } Data; 
  } NotifyData; 
} PRINTER_NOTIFY_INFO_DATA, *PPRINTER_NOTIFY_INFO_DATA;

------解决方案--------------------
Codeplex上的一个项目也有过同样的问题,解决方案来自 不存在的网站
代码如下:
C# code

[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_NOTIFY_INFO_DATA_DATA
{
  public uint cbBuf;
  public IntPtr pBuf;
}

[StructLayout(LayoutKind.Explicit)]
public struct PRINTER_NOTIFY_INFO_DATA_UNION
{
  [FieldOffset(0)]
  private uint adwData0;
  [FieldOffset(4)]
  private uint adwData1;
  [FieldOffset(0)]
  public PRINTER_NOTIFY_INFO_DATA_DATA Data;
  public uint[] adwData
  {
    get
    {
      return new uint[] { this.adwData0, this.adwData1 };
    }
  }
}

[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_NOTIFY_INFO_DATA
{
  public ushort Type;
  public ushort Field;
  public uint Reserved;
  public uint Id;
  public PRINTER_NOTIFY_INFO_DATA_UNION NotifyData;
}

------解决方案--------------------
64位下,adwData0和cbBuf应当具有相同值,adwData1的值不能由Data取到,因为pBuf之前有4字节被空置以对齐。
------解决方案--------------------
PRINTER_NOTIFY_INFO的代码也是有的,出处同上
C# code

[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_NOTIFY_INFO
{
  public uint Version;
  public uint Flags;
  public uint Count;
  [MarshalAs(UnmanagedType.ByValArray, SizeConst=1)]
  public PRINTER_NOTIFY_INFO_DATA[] aData;
}