2012-10-09 17 views
9

私は基本的にコンピュータの印刷アクティビティを監視するコードプロジェクトからプロジェクトをプレイしていました。ただし、64ビット構成では正しく動作しません。コードの以下の部分が問題でした。このコードは、印刷が完了するたびに呼び出されます。PRINT_NOTIFY_INFO_DATAを正しく定義する方法は?

PRINTER_NOTIFY_INFO info = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO));       
int pData = (int)pNotifyInfo + Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO)); 
PRINTER_NOTIFY_INFO_DATA[] data = new PRINTER_NOTIFY_INFO_DATA[info.Count]; 
for (uint i = 0; i < info.Count; i++) 
{ 
    data[i] = (PRINTER_NOTIFY_INFO_DATA)Marshal.PtrToStructure((IntPtr)pData, typeof(PRINTER_NOTIFY_INFO_DATA)); 
    pData += Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO_DATA)); 
} 

デバッグでは、data [i] .field値が常に0であることが示されていますが、32ビットでは正しく動作します。私はPRINTER_NOTIFY_INFO_DATAが正しく定義されていないと思います。現在私は次のコードを使用しています。誰も64ビットで正しく動作するようにこれを修正できますか?

[StructLayout(LayoutKind.Sequential)] 
public struct PRINTER_NOTIFY_INFO 
{ 
    public uint Version; 
    public uint Flags; 
    public uint Count; 
} 


[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 }; 
     } 
    } 
} 

// Structure borrowed from http://lifeandtimesofadeveloper.blogspot.com/2007/10/unmanaged-structures-padding-and-c-part_18.html. 
[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; 
} 

MS XPSドライバを使用して印刷をテストしていました。コードプロジェクトの記事はHere

答えて

14

Data Alignmentのため64ビット構成では正しく動作しません。

だから私は、次のようにPRINTER_NOTIFY_INFOを変更することをお勧め:その後、

[StructLayout(LayoutKind.Sequential)] 
public struct PRINTER_NOTIFY_INFO 
{ 
    public uint Version; 
    public uint Flags; 
    public uint Count; 
    public PRINTER_NOTIFY_INFO_DATA_UNION aData; 
} 

そしてMarshal.SizeOfの代わりにMarshal.OffsetOfを使用する:

PRINTER_NOTIFY_INFO info = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO));       
long pData = (long)pNotifyInfo + (long)Marshal.OffsetOf(typeof(PRINTER_NOTIFY_INFO), "aData"); 
PRINTER_NOTIFY_INFO_DATA[] data = new PRINTER_NOTIFY_INFO_DATA[info.Count]; 
for (uint i = 0; i < info.Count; i++) 
{ 
    data[i] = (PRINTER_NOTIFY_INFO_DATA)Marshal.PtrToStructure((IntPtr)pData, typeof(PRINTER_NOTIFY_INFO_DATA)); 
    pData += (long)Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO_DATA)); 
} 
+0

あなたは万人ありがとう、私の命を救いました。 –

+0

さらに、関連するプロジェクトがx86実行可能ファイルをビルドするように構成されていることを確認してください。 –

+0

これに注意するべきいくつかの事柄。 1)Marshal.OffsetOf()はIntPtrオブジェクトを返します。私の知る限り、long型に直接キャストすることはできません。 IntPtr.ToInt32()メソッドを使用する必要があります。 2)PRINTER_NOTIFY_INFO.Countが0の場合、このコードによってコードがクラッシュする可能性があります。これは、aData []リストに構造体がないことを意味します。記述した方法で宣言することで、配列内に少なくとも1つのオブジェクトが保証されます。 countが0の場合は、セグメンテーション違反の可能性があります。私は代わりにIntPtrとしてaDataを宣言しています。本当に、アンマネージコードの中では、ちょうどポインタです。 – Ultratrunks

関連する問題