C#调用winspool.drvGetJob函数时出现异常
An exception occur when Calling winspool.drv GetJob function in C#
这是我的主程序:
class Program
{
static void Main(string[] args)
{
Printer printer = new Printer();
IntPtr printerHandle = printer.getPrinterHandle("TASKalfa 2551ci");
UInt32 jobId = printer.getJobId();
Console.WriteLine(printerHandle+","+jobId);
printer.getJob(printerHandle, jobId);
Console.ReadLine();
}
}
当我调用 printer.getJob 方法时,我从 VS 2015 Community Edition 收到以下错误消息,即使我已经捕获了 System.NullReferenceException.
System.NullReferenceException was unhandled
Message: An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll
Additional information: Object reference not set to an instance of an object.
我已经检查过变量 printerHandle 和 jobId 都不为空,所以我不知道是什么问题。
但是 printerHandle 的值不是常量,对吗?
这是我的打印机对象源代码:
using System;
using System.Collections;
using System.Management;
using System.Runtime.InteropServices;
class Printer
{
public Printer()
{
}
public ArrayList getPrinterNameList()
{
ArrayList result = new ArrayList();
var printerQuery = new ManagementObjectSearcher("SELECT * from Win32_Printer");
foreach (var printer in printerQuery.Get())
{
result.Add(printer.GetPropertyValue("Name"));
}
return result;
}
public UInt32 getJobId()
{
UInt32 jobId=0;
var printJobQuery = new ManagementObjectSearcher("select * from Win32_PrintJob");
foreach (var printJob in printJobQuery.Get())
{
jobId= (UInt32)printJob.Properties["JobId"].Value;
}
return jobId;
}
public IntPtr getPrinterHandle(String printerName)
{
IntPtr result=new IntPtr(0);
Console.WriteLine ("OpenPrinter="+OpenPrinter(printerName,out result, result));
return result;
}
public void getJob(IntPtr printerHandle,UInt32 jobId)
{
int BUFFER_SIZE = 250;
IntPtr pcbNeeed = new IntPtr(0);
byte[] byteBuffer = new byte[BUFFER_SIZE];
try
{
Console.WriteLine("GetJob="+GetJob(printerHandle, (Int32)jobId, 1, out byteBuffer, BUFFER_SIZE, out pcbNeeed));
}
catch (System.NullReferenceException err)
{
Console.WriteLine(err.Message);
}
}
[DllImport("winspool.drv", SetLastError = true)]
static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);
[DllImport(
"winspool.drv",
EntryPoint = "GetJobW",
SetLastError = true,
CharSet = CharSet.Ansi,
ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
private static extern bool GetJob
([InAttribute()] IntPtr hPrinter,
[InAttribute()] Int32 JobId,
[InAttribute()] Int32 Level,
[OutAttribute()] out byte[] pJob,
[InAttribute()] Int32 cbBuf,
[OutAttribute()] out IntPtr pcbNeeded);
}
这是我的 WIN API 版本:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string msg = null;
var hPrinter = new IntPtr();
bool open = NativeMethods.OpenPrinterW("TASKalfa 2551ci", ref hPrinter, IntPtr.Zero);
Debug.Assert(open);
/* Query for 99 jobs */
const uint firstJob = 0u;
const uint noJobs = 99u;
const uint level = 1u;
// Get byte size required for the function
uint needed;
uint returned;
IntPtr tempptr = IntPtr.Zero;
bool b1 = NativeMethods.EnumJobsW(
hPrinter, firstJob, noJobs, level, IntPtr.Zero, 0, out needed, out returned);
uint lastError = NativeMethods.GetLastError();
Console.WriteLine("b1="+b1);
//Debug.Assert(lastError == NativeConstants.ERROR_INSUFFICIENT_BUFFER);
NativeMethods.FormatMessage(0x1300, ref tempptr, lastError, 0, ref msg, 255, ref tempptr);
Console.WriteLine("lastError=" + msg);
// Populate the structs
IntPtr pJob = Marshal.AllocHGlobal((int)needed);
uint bytesCopied;
uint structsCopied;
bool b2 = NativeMethods.EnumJobsW(
hPrinter, firstJob, noJobs, level, pJob, needed, out bytesCopied, out structsCopied);
lastError = NativeMethods.GetLastError();
Console.WriteLine("b2="+b2);
NativeMethods.FormatMessage(0x1300, ref tempptr, lastError, 0, ref msg, 255, ref tempptr);
Console.WriteLine("lastError="+ msg);
var jobInfos = new JOB_INFO_1W[structsCopied];
int sizeOf = Marshal.SizeOf(typeof(JOB_INFO_1W));
IntPtr pStruct = pJob;
for (int i = 0; i < structsCopied; i++)
{
var jobInfo_1W = (JOB_INFO_1W)Marshal.PtrToStructure(pStruct, typeof(JOB_INFO_1W));
jobInfos[i] = jobInfo_1W;
pStruct += sizeOf;
}
Marshal.FreeHGlobal(pJob);
Console.WriteLine("structsCopied="+structsCopied);
Console.ReadLine();
}
public class NativeConstants
{
public const int ERROR_INSUFFICIENT_BUFFER = 122;
}
public partial class NativeMethods
{
[DllImport("kernel32.dll", EntryPoint = "GetLastError")]
public static extern uint GetLastError();
[System.Runtime.InteropServices.DllImport("Kernel32.dll")]
public extern static int FormatMessage(int flag, ref IntPtr source, uint msgid, int langid, ref string buf, int size, ref IntPtr args);
}
public partial class NativeMethods
{
[DllImport("Winspool.drv", EntryPoint = "OpenPrinterW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenPrinterW([In] [MarshalAs(UnmanagedType.LPWStr)] string pPrinterName,
ref IntPtr phPrinter, [In] IntPtr pDefault);
[DllImport("Winspool.drv", EntryPoint = "EnumJobsW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumJobsW([In] IntPtr hPrinter, uint FirstJob, uint NoJobs, uint Level, IntPtr pJob,
uint cbBuf, [Out] out uint pcbNeeded, [Out] out uint pcReturned);
}
[StructLayout(LayoutKind.Sequential)]
public struct JOB_INFO_1W
{
public uint JobId;
[MarshalAs(UnmanagedType.LPWStr)]
public string pPrinterName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pMachineName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pUserName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pDocument;
[MarshalAs(UnmanagedType.LPWStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPWStr)]
public string pStatus;
public uint Status;
public uint Priority;
public uint Position;
public uint TotalPages;
public uint PagesPrinted;
public SYSTEMTIME Submitted;
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
}
}
我正在使用 Windows10.
这是我的解决方案:
using System;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;
namespace WinApi
{
class PrintJob
{
private const int ERROR_INSUFFICIENT_BUFFER = 122;
public PrintJob()
{
string sql = "select * from Win32_PrintJob";
var printJobQuery = new ManagementObjectSearcher(sql);
foreach (ManagementObject printJob in printJobQuery.Get())
{
getJobDetail(printJob);
Console.WriteLine("====================");
}
}
private void getJobDetail(ManagementObject thePrintJob)
{
UInt32 jobId = 0, needed = 0;
String printerName;
bool result;
IntPtr printerHandle = new IntPtr(0);
jobId = (UInt32)thePrintJob.Properties["JobId"].Value;
printerName = (String)thePrintJob.Properties["DriverName"].Value;
Console.WriteLine("Job Id=" + jobId + ",Printer Name=" + printerName);
result=OpenPrinter(printerName,out printerHandle, IntPtr.Zero);
Console.Write("Open Printer " + printerName);
if (result)
{
Console.WriteLine(" success.");
result = GetJob(printerHandle, jobId, 2, IntPtr.Zero,0,out needed);
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
Console.WriteLine("Get Job 1 failure, error code=" + Marshal.GetLastWin32Error());
else
{
Console.WriteLine("buffer size required=" + needed);
IntPtr buffer = Marshal.AllocHGlobal((int)needed);
result = GetJob(printerHandle, jobId, 2, buffer, needed, out needed);
JOB_INFO_2 jobInfo=(JOB_INFO_2)Marshal.PtrToStructure(buffer, typeof(JOB_INFO_2));
DEVMODE dMode = (DEVMODE)Marshal.PtrToStructure(jobInfo.pDevMode, typeof(DEVMODE));
Console.WriteLine("Job Id=" + jobInfo.JobId + ",Printer Name=" + Marshal.PtrToStringAnsi(jobInfo.pDriverName) + ",Copies=" + dMode.dmCopies);
Marshal.FreeHGlobal(buffer);
}
ClosePrinter(printerHandle);
Console.WriteLine("Printer " + printerName+" is closed");
}
else
Console.WriteLine(" failed.");
}
[DllImport("winspool.drv", SetLastError = true)]
static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);
[DllImport("winspool.drv", CharSet = CharSet.Auto)]
static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport(
"winspool.drv",
EntryPoint = "GetJob",
SetLastError = true,
ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
private static extern bool GetJob
([InAttribute()] IntPtr hPrinter,
[InAttribute()] UInt32 JobId,
[InAttribute()] UInt32 Level,
[OutAttribute()] IntPtr pJob,
[InAttribute()] UInt32 cbBuf,
[OutAttribute()] out UInt32 pcbNeeded);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct JOB_INFO_2
{
public UInt32 JobId;
public IntPtr pPrinterName;
public IntPtr pMachineName;
public IntPtr pUserName;
public IntPtr pDocument;
public IntPtr pNotifyName;
public IntPtr pDatatype;
public IntPtr pPrintProcessor;
public IntPtr pParameters;
public IntPtr pDriverName;
public IntPtr pDevMode;
public IntPtr pStatus;
public IntPtr pSecurityDescriptor;
public UInt32 Status;
public UInt32 Priority;
public UInt32 Position;
public UInt32 StartTime;
public UInt32 UntilTime;
public UInt32 TotalPages;
public UInt32 Size;
public SYSTEMTIME Submitted;
public UInt32 Time;
public UInt32 PagesPrinted;
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}
}
}
这是我的主程序:
class Program
{
static void Main(string[] args)
{
Printer printer = new Printer();
IntPtr printerHandle = printer.getPrinterHandle("TASKalfa 2551ci");
UInt32 jobId = printer.getJobId();
Console.WriteLine(printerHandle+","+jobId);
printer.getJob(printerHandle, jobId);
Console.ReadLine();
}
}
当我调用 printer.getJob 方法时,我从 VS 2015 Community Edition 收到以下错误消息,即使我已经捕获了 System.NullReferenceException.
System.NullReferenceException was unhandled
Message: An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll
Additional information: Object reference not set to an instance of an object.
我已经检查过变量 printerHandle 和 jobId 都不为空,所以我不知道是什么问题。
但是 printerHandle 的值不是常量,对吗?
这是我的打印机对象源代码:
using System;
using System.Collections;
using System.Management;
using System.Runtime.InteropServices;
class Printer
{
public Printer()
{
}
public ArrayList getPrinterNameList()
{
ArrayList result = new ArrayList();
var printerQuery = new ManagementObjectSearcher("SELECT * from Win32_Printer");
foreach (var printer in printerQuery.Get())
{
result.Add(printer.GetPropertyValue("Name"));
}
return result;
}
public UInt32 getJobId()
{
UInt32 jobId=0;
var printJobQuery = new ManagementObjectSearcher("select * from Win32_PrintJob");
foreach (var printJob in printJobQuery.Get())
{
jobId= (UInt32)printJob.Properties["JobId"].Value;
}
return jobId;
}
public IntPtr getPrinterHandle(String printerName)
{
IntPtr result=new IntPtr(0);
Console.WriteLine ("OpenPrinter="+OpenPrinter(printerName,out result, result));
return result;
}
public void getJob(IntPtr printerHandle,UInt32 jobId)
{
int BUFFER_SIZE = 250;
IntPtr pcbNeeed = new IntPtr(0);
byte[] byteBuffer = new byte[BUFFER_SIZE];
try
{
Console.WriteLine("GetJob="+GetJob(printerHandle, (Int32)jobId, 1, out byteBuffer, BUFFER_SIZE, out pcbNeeed));
}
catch (System.NullReferenceException err)
{
Console.WriteLine(err.Message);
}
}
[DllImport("winspool.drv", SetLastError = true)]
static extern int OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);
[DllImport(
"winspool.drv",
EntryPoint = "GetJobW",
SetLastError = true,
CharSet = CharSet.Ansi,
ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
private static extern bool GetJob
([InAttribute()] IntPtr hPrinter,
[InAttribute()] Int32 JobId,
[InAttribute()] Int32 Level,
[OutAttribute()] out byte[] pJob,
[InAttribute()] Int32 cbBuf,
[OutAttribute()] out IntPtr pcbNeeded);
}
这是我的 WIN API 版本:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string msg = null;
var hPrinter = new IntPtr();
bool open = NativeMethods.OpenPrinterW("TASKalfa 2551ci", ref hPrinter, IntPtr.Zero);
Debug.Assert(open);
/* Query for 99 jobs */
const uint firstJob = 0u;
const uint noJobs = 99u;
const uint level = 1u;
// Get byte size required for the function
uint needed;
uint returned;
IntPtr tempptr = IntPtr.Zero;
bool b1 = NativeMethods.EnumJobsW(
hPrinter, firstJob, noJobs, level, IntPtr.Zero, 0, out needed, out returned);
uint lastError = NativeMethods.GetLastError();
Console.WriteLine("b1="+b1);
//Debug.Assert(lastError == NativeConstants.ERROR_INSUFFICIENT_BUFFER);
NativeMethods.FormatMessage(0x1300, ref tempptr, lastError, 0, ref msg, 255, ref tempptr);
Console.WriteLine("lastError=" + msg);
// Populate the structs
IntPtr pJob = Marshal.AllocHGlobal((int)needed);
uint bytesCopied;
uint structsCopied;
bool b2 = NativeMethods.EnumJobsW(
hPrinter, firstJob, noJobs, level, pJob, needed, out bytesCopied, out structsCopied);
lastError = NativeMethods.GetLastError();
Console.WriteLine("b2="+b2);
NativeMethods.FormatMessage(0x1300, ref tempptr, lastError, 0, ref msg, 255, ref tempptr);
Console.WriteLine("lastError="+ msg);
var jobInfos = new JOB_INFO_1W[structsCopied];
int sizeOf = Marshal.SizeOf(typeof(JOB_INFO_1W));
IntPtr pStruct = pJob;
for (int i = 0; i < structsCopied; i++)
{
var jobInfo_1W = (JOB_INFO_1W)Marshal.PtrToStructure(pStruct, typeof(JOB_INFO_1W));
jobInfos[i] = jobInfo_1W;
pStruct += sizeOf;
}
Marshal.FreeHGlobal(pJob);
Console.WriteLine("structsCopied="+structsCopied);
Console.ReadLine();
}
public class NativeConstants
{
public const int ERROR_INSUFFICIENT_BUFFER = 122;
}
public partial class NativeMethods
{
[DllImport("kernel32.dll", EntryPoint = "GetLastError")]
public static extern uint GetLastError();
[System.Runtime.InteropServices.DllImport("Kernel32.dll")]
public extern static int FormatMessage(int flag, ref IntPtr source, uint msgid, int langid, ref string buf, int size, ref IntPtr args);
}
public partial class NativeMethods
{
[DllImport("Winspool.drv", EntryPoint = "OpenPrinterW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool OpenPrinterW([In] [MarshalAs(UnmanagedType.LPWStr)] string pPrinterName,
ref IntPtr phPrinter, [In] IntPtr pDefault);
[DllImport("Winspool.drv", EntryPoint = "EnumJobsW")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumJobsW([In] IntPtr hPrinter, uint FirstJob, uint NoJobs, uint Level, IntPtr pJob,
uint cbBuf, [Out] out uint pcbNeeded, [Out] out uint pcReturned);
}
[StructLayout(LayoutKind.Sequential)]
public struct JOB_INFO_1W
{
public uint JobId;
[MarshalAs(UnmanagedType.LPWStr)]
public string pPrinterName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pMachineName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pUserName;
[MarshalAs(UnmanagedType.LPWStr)]
public string pDocument;
[MarshalAs(UnmanagedType.LPWStr)]
public string pDatatype;
[MarshalAs(UnmanagedType.LPWStr)]
public string pStatus;
public uint Status;
public uint Priority;
public uint Position;
public uint TotalPages;
public uint PagesPrinted;
public SYSTEMTIME Submitted;
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public ushort wYear;
public ushort wMonth;
public ushort wDayOfWeek;
public ushort wDay;
public ushort wHour;
public ushort wMinute;
public ushort wSecond;
public ushort wMilliseconds;
}
}
}
我正在使用 Windows10.
这是我的解决方案:
using System;
using System.Text;
using System.Management;
using System.Runtime.InteropServices;
namespace WinApi
{
class PrintJob
{
private const int ERROR_INSUFFICIENT_BUFFER = 122;
public PrintJob()
{
string sql = "select * from Win32_PrintJob";
var printJobQuery = new ManagementObjectSearcher(sql);
foreach (ManagementObject printJob in printJobQuery.Get())
{
getJobDetail(printJob);
Console.WriteLine("====================");
}
}
private void getJobDetail(ManagementObject thePrintJob)
{
UInt32 jobId = 0, needed = 0;
String printerName;
bool result;
IntPtr printerHandle = new IntPtr(0);
jobId = (UInt32)thePrintJob.Properties["JobId"].Value;
printerName = (String)thePrintJob.Properties["DriverName"].Value;
Console.WriteLine("Job Id=" + jobId + ",Printer Name=" + printerName);
result=OpenPrinter(printerName,out printerHandle, IntPtr.Zero);
Console.Write("Open Printer " + printerName);
if (result)
{
Console.WriteLine(" success.");
result = GetJob(printerHandle, jobId, 2, IntPtr.Zero,0,out needed);
if (Marshal.GetLastWin32Error() != ERROR_INSUFFICIENT_BUFFER)
Console.WriteLine("Get Job 1 failure, error code=" + Marshal.GetLastWin32Error());
else
{
Console.WriteLine("buffer size required=" + needed);
IntPtr buffer = Marshal.AllocHGlobal((int)needed);
result = GetJob(printerHandle, jobId, 2, buffer, needed, out needed);
JOB_INFO_2 jobInfo=(JOB_INFO_2)Marshal.PtrToStructure(buffer, typeof(JOB_INFO_2));
DEVMODE dMode = (DEVMODE)Marshal.PtrToStructure(jobInfo.pDevMode, typeof(DEVMODE));
Console.WriteLine("Job Id=" + jobInfo.JobId + ",Printer Name=" + Marshal.PtrToStringAnsi(jobInfo.pDriverName) + ",Copies=" + dMode.dmCopies);
Marshal.FreeHGlobal(buffer);
}
ClosePrinter(printerHandle);
Console.WriteLine("Printer " + printerName+" is closed");
}
else
Console.WriteLine(" failed.");
}
[DllImport("winspool.drv", SetLastError = true)]
static extern bool OpenPrinter(string pPrinterName, out IntPtr phPrinter, IntPtr pDefault);
[DllImport("winspool.drv", CharSet = CharSet.Auto)]
static extern bool ClosePrinter(IntPtr hPrinter);
[DllImport(
"winspool.drv",
EntryPoint = "GetJob",
SetLastError = true,
ExactSpelling = false,
CallingConvention = CallingConvention.StdCall)]
private static extern bool GetJob
([InAttribute()] IntPtr hPrinter,
[InAttribute()] UInt32 JobId,
[InAttribute()] UInt32 Level,
[OutAttribute()] IntPtr pJob,
[InAttribute()] UInt32 cbBuf,
[OutAttribute()] out UInt32 pcbNeeded);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct JOB_INFO_2
{
public UInt32 JobId;
public IntPtr pPrinterName;
public IntPtr pMachineName;
public IntPtr pUserName;
public IntPtr pDocument;
public IntPtr pNotifyName;
public IntPtr pDatatype;
public IntPtr pPrintProcessor;
public IntPtr pParameters;
public IntPtr pDriverName;
public IntPtr pDevMode;
public IntPtr pStatus;
public IntPtr pSecurityDescriptor;
public UInt32 Status;
public UInt32 Priority;
public UInt32 Position;
public UInt32 StartTime;
public UInt32 UntilTime;
public UInt32 TotalPages;
public UInt32 Size;
public SYSTEMTIME Submitted;
public UInt32 Time;
public UInt32 PagesPrinted;
}
[StructLayout(LayoutKind.Sequential)]
public struct SYSTEMTIME
{
public short wYear;
public short wMonth;
public short wDayOfWeek;
public short wDay;
public short wHour;
public short wMinute;
public short wSecond;
public short wMilliseconds;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct DEVMODE
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmDeviceName;
public short dmSpecVersion;
public short dmDriverVersion;
public short dmSize;
public short dmDriverExtra;
public int dmFields;
public short dmOrientation;
public short dmPaperSize;
public short dmPaperLength;
public short dmPaperWidth;
public short dmScale;
public short dmCopies;
public short dmDefaultSource;
public short dmPrintQuality;
public short dmColor;
public short dmDuplex;
public short dmYResolution;
public short dmTTOption;
public short dmCollate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
public string dmFormName;
public short dmLogPixels;
public int dmBitsPerPel;
public int dmPelsWidth;
public int dmPelsHeight;
public int dmDisplayFlags;
public int dmDisplayFrequency;
}
}
}