C#.NET Framework 3.5:打印pdf时在运行时更改打印机设置

C#.NET Framework 3.5:打印pdf时在运行时更改打印机设置,c#,.net,pdf,printing,C#,.net,Pdf,Printing,​我正在使用VS2010。NET框架3.5 先决条件: 系统上未安装Adobe 不使用第三方DLL 应使用Windows DLL 到目前为止,我可以打印pdf文件,但无法在运行时更改打印机设置 打印pdf文件的基本思想是,我读取pdf文件的字节,然后直接将它们发送到打印机。在这里,它可以毫无问题地打印pdf文件 但是文件在一页上并排打印,但是我希望它只打印页面的一面,而不是两面。为此,我尝试在运行时更改打印机设置 我已经在两台不同的打印机上测试了我的代码。在一台打印机上,它在同一页上并排打印,而

​我正在使用VS2010。NET框架3.5

先决条件:

  • 系统上未安装Adobe

  • 不使用第三方DLL

  • 应使用Windows DLL

  • 到目前为止,我可以打印pdf文件,但无法在运行时更改打印机设置

    打印pdf文件的基本思想是,我读取pdf文件的字节,然后直接将它们发送到打印机。在这里,它可以毫无问题地打印pdf文件

    但是文件在一页上并排打印,但是我希望它只打印页面的一面,而不是两面。为此,我尝试在运行时更改打印机设置

    我已经在两台不同的打印机上测试了我的代码。在一台打印机上,它在同一页上并排打印,而在另一台打印机上仅在一页上打印。这意味着,打印机设置不会更改

    代码如下所示。使用了4个类:

    //Class 1: This class basically tries to change the printer setting at run time
    
     public class PrinterSettingForPdf
    
    {
    
     #region "Private Variables"
    
     private IntPtr hPrinter = new System.IntPtr();
    
     private PRINTER_DEFAULTS PrinterValues = new PRINTER_DEFAULTS();
    
     private PRINTER_INFO_2 pinfo = new PRINTER_INFO_2();
    
     //private PRINTER_INFO_9 pinfo9 = new PRINTER_INFO_9();
    
     private DEVMODE dm;
    
     private IntPtr ptrDM;
    
     private IntPtr ptrPrinterInfo;
    
     private int sizeOfDevMode = 0;
    
     private int lastError;
    
     private int nBytesNeeded;
    
     private long nRet;
    
     private int intError;
    
     private System.Int32 nJunk;
    
     private IntPtr yDevModeData;
    
    #endregion
    
     #region "Constants"
    
     private const int DM_DUPLEX = 0x1000;
    
     private const int DM_IN_BUFFER = 8;
    
     private const int DM_OUT_BUFFER = 2;
    
     private const int PRINTER_ACCESS_ADMINISTER = 0x4;
    
     private const int PRINTER_ACCESS_USE = 0x8;
    
     private const int STANDARD_RIGHTS_REQUIRED = 0xF0000;
    
     private const int PRINTER_ALL_ACCESS =
    
    (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER
    
    | PRINTER_ACCESS_USE);
    
    #endregion
    
     #region "Win API Def"
    
     [DllImport("kernel32.dll", EntryPoint = "GetLastError", SetLastError = false,
    
     ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     private static extern Int32 GetLastError();
    
     [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true,
    
     ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     private static extern bool ClosePrinter(IntPtr hPrinter);
    
     [DllImport("winspool.Drv", EntryPoint = "DocumentPropertiesA", SetLastError = true,
    
     ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     private static extern int DocumentProperties(IntPtr hwnd, IntPtr hPrinter,
    
     [MarshalAs(UnmanagedType.LPStr)] string pDeviceNameg,
    
     IntPtr pDevModeOutput, ref IntPtr pDevModeInput, int fMode);
    
     [DllImport("winspool.Drv", EntryPoint = "GetPrinterA", SetLastError = true,
    
     CharSet = CharSet.Ansi, ExactSpelling = true,
    
     CallingConvention = CallingConvention.StdCall)]
    
     private static extern bool GetPrinter(IntPtr hPrinter, Int32 dwLevel,
    
     IntPtr pPrinter, Int32 dwBuf, out Int32 dwNeeded);
    
     [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA",
    
     SetLastError = true, CharSet = CharSet.Ansi,
    
     ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     private static extern bool
    
     OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter,
    
     out IntPtr hPrinter, ref PRINTER_DEFAULTS pd);
    
     [DllImport("winspool.drv", CharSet = CharSet.Ansi, SetLastError = true)]
    
     private static extern bool SetPrinter(IntPtr hPrinter, int Level, IntPtr
    
     pPrinter, int Command);
    
    #endregion
    
     #region "Data structure"
    
     [StructLayout(LayoutKind.Sequential)]
    
     public struct PRINTER_DEFAULTS
    
    {
    
     public int pDatatype;
    
     public int pDevMode;
    
     public int DesiredAccess;
    
    }
    
     [StructLayout(LayoutKind.Sequential)]
    
     private struct PRINTER_INFO_2
    
    {
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pServerName;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pPrinterName;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pShareName;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pPortName;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pDriverName;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pComment;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pLocation;
    
     public IntPtr pDevMode;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pSepFile;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pPrintProcessor;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pDatatype;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pParameters;
    
     public IntPtr pSecurityDescriptor;
    
     public Int32 Attributes;
    
     public Int32 Priority;
    
     public Int32 DefaultPriority;
    
     public Int32 StartTime;
    
     public Int32 UntilTime;
    
     public Int32 Status;
    
     public Int32 cJobs;
    
     public Int32 AveragePPM;
    
    }
    
     /// <summary>
    
     /// The PRINTER_INFO_9 structure specifies the per-user default printer settings.
    
     /// </summary>
    
     /// <seealso href="http://msdn.microsoft.com/en-us/library/windows/desktop/dd162852(v=vs.85).aspx"/>
    
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    
     internal class PRINTER_INFO_9
    
    {
    
     /// <summary>
    
     /// A pointer to a DEVMODE structure that defines the per-user
    
     /// default printer data such as the paper orientation and the resolution.
    
     /// The DEVMODE is stored in the user's registry.
    
     /// </summary>
    
     public IntPtr pDevMode;
    
    }
    
     private const short CCDEVICENAME = 32;
    
     private const short CCFORMNAME = 32;
    
     [StructLayout(LayoutKind.Sequential)]
    
     public struct DEVMODE
    
    {
    
     [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCDEVICENAME)]
    
     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 = CCFORMNAME)]
    
     public string dmFormName;
    
     public short dmUnusedPadding;
    
     public short dmBitsPerPel;
    
     public int dmPelsWidth;
    
     public int dmPelsHeight;
    
     public int dmDisplayFlags;
    
     public int dmDisplayFrequency;
    
    }
    
    #endregion
    
     #region "Function to change printer settings"
    
    
     public bool ChangePrintersetting(string sPrinterName, PrinterData pd, int numbeOfCopies, bool preserverOldSettings)
    
    {
    
     if (((int)pd.Duplex < 1) || ((int)pd.Duplex > 3))
    
    {
    
     throw new ArgumentOutOfRangeException("nDuplexSetting", "nDup lexSetting is incorrect.");
    
    }
    
     else
    
    {
    
     const int PRINTER_ACCESS_ADMINISTER = 0x4;
    
     const int PRINTER_ACCESS_USE = 0x8;
    
     const int PRINTER_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | PRINTER_ACCESS_ADMINISTER | PRINTER_ACCESS_USE);
    
     //const int READ_CONTROL = 0x20000;
    
     //const int PRINTER_NORMAL_ACCESS = 131080; // (READ_CONTROL | PRINTER_ACCESS_USE);
    
    PrinterValues.pDatatype = 0;
    
    PrinterValues.pDevMode = 0;
    
    PrinterValues.DesiredAccess = PRINTER_ALL_ACCESS;
    
     nRet = Convert.ToInt32(OpenPrinter(sPrinterName, out hPrinter, ref PrinterValues));
    
     if (nRet == 0)
    
    {
    
     lastError = Marshal.GetLastWin32Error();
    
     throw new Win32Exception(Marshal.GetLastWin32Error());
    
    }
    
     GetPrinter(hPrinter, 2, IntPtr.Zero, 0, out nBytesNeeded);
    
     if (nBytesNeeded <= 0)
    
    {
    
     return false;
    
    }
    
     // Allocate enough space for PRINTER_INFO_2...
    
     //ptrPrinterInfo = Marshal.AllocCoTaskMem(nBytesNeeded);
    
     ptrPrinterInfo = Marshal.AllocHGlobal(nBytesNeeded);
    
     // The second GetPrinter fills in all the current settings, so all you
    
     // need to do is modify what you're interested in...
    
     nRet = Convert.ToInt32(GetPrinter(hPrinter, 2, ptrPrinterInfo, nBytesNeeded, out nJunk));
    
     if (nRet == 0)
    
    {
    
     lastError = Marshal.GetLastWin32Error();
    
     throw new Win32Exception(Marshal.GetLastWin32Error());
    
    }
    
     pinfo = (PRINTER_INFO_2)Marshal.PtrToStructure(ptrPrinterInfo, typeof(PRINTER_INFO_2));
    
     IntPtr Temp = new IntPtr();
    
     int i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, IntPtr.Zero, ref Temp, 0);
    
     //IntPtr yDevModeData = Marshal.AllocCoTaskMem(i1);
    
     IntPtr yDevModeData = Marshal.AllocHGlobal(i1);
    
     i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData, ref Temp, 2);
    
     dm = (DEVMODE)Marshal.PtrToStructure(yDevModeData, typeof(DEVMODE));
    
     dm.dmDefaultSource = (short)pd.Source;
    
     dm.dmOrientation = (short)pd.Orientation;
    
     dm.dmPaperSize = (short)pd.Size;
    
     dm.dmCopies = (short)1;
    
     dm.dmDuplex = (short)pd.Duplex;
    
     Marshal.StructureToPtr(dm, yDevModeData, true);
    
     //nRet = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
    
     // , ref yDevModeData, (DM_IN_BUFFER | DM_OUT_BUFFER));
    
     if ((nRet == 0) || (hPrinter == IntPtr.Zero))
    
    {
    
     lastError = Marshal.GetLastWin32Error();
    
     //string myErrMsg = GetErrorMessage(lastError);
    
     throw new Win32Exception(Marshal.GetLastWin32Error());
    
    }
    
     if (pinfo.pDevMode == IntPtr.Zero)
    
    {
    
     // If GetPrinter didn't fill in the DEVMODE, try to get it by calling
    
     // DocumentProperties...
    
     IntPtr ptrZero = IntPtr.Zero;
    
     //get the size of the devmode structure
    
     sizeOfDevMode = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, ptrZero, ref ptrZero, 0);
    
     if (nRet <= 0)
    
    {
    
     return false;
    
    }
    
     ptrDM = Marshal.AllocCoTaskMem(sizeOfDevMode);
    
     int i;
    
     i = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, ptrDM,
    
     ref ptrZero, DM_OUT_BUFFER);
    
     if ((i < 0) || (ptrDM == IntPtr.Zero))
    
    {
    
     //Cannot get the DEVMODE structure.
    
     return false;
    
    }
    
    pinfo.pDevMode = ptrDM;
    
    }
    
     if (!Convert.ToBoolean(dm.dmFields & DM_DUPLEX))
    
    {
    
     //You cannot modify the duplex flag for this printer
    
     //because it does not support duplex or the driver does not support setting
    
     //it from the Windows API.
    
     //return false;
    
    }
    
    pinfo.pDevMode = yDevModeData;
    
     pinfo.pSecurityDescriptor = IntPtr.Zero;
    
     /*update driver dependent part of the DEVMODE
    
    i1 = DocumentProperties(IntPtr.Zero, hPrinter, sPrinterName, yDevModeData
    
    , ref pinfo.pDevMode, (DM_IN_BUFFER | DM_OUT_BUFFER));*/
    
     if (i1 < 0)
    
    {
    
     //Unable to set duplex setting to this printer.
    
     return false;
    
    }
    
     Marshal.StructureToPtr(pinfo, ptrPrinterInfo, true);
    
     lastError = Marshal.GetLastWin32Error();
    
     nRet = Convert.ToInt16(SetPrinter(hPrinter, 2, ptrPrinterInfo, 0));
    
     if (nRet == 0)
    
    {
    
     //Unable to set shared printer settings.
    
     lastError = Marshal.GetLastWin32Error();
    
     //string myErrMsg = GetErrorMessage(lastError);
    
     throw new Win32Exception(Marshal.GetLastWin32Error());
    
    }
    
     return Convert.ToBoolean(nRet);
    
    }
    
    }
    
    #endregion
    
    }
    
    
    //Class 2: Supporting Printer setting class
    
    public class PrinterData
    
    {
    
     public int Duplex { get; set; }
    
     public int Source { get; set; }
    
     public int Orientation { get; set; }
    
     public int Size { get; set; }
    
    }
    
    
    //Class 3: This class uses Windows dlls methods to print pdf contents
    
    public class PrintPdf
    
    {
    
     // Structure and API declarions:
    
     [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    
     public class DOCINFOA
    
    {
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pDocName;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pOutputFile;
    
     [MarshalAs(UnmanagedType.LPStr)]
    
     public string pDataType;
    
    }
    
     [DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd);
    
     [DllImport("winspool.Drv", EntryPoint = "ClosePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     public static extern bool ClosePrinter(IntPtr hPrinter);
    
     [DllImport("winspool.Drv", EntryPoint = "StartDocPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     public static extern bool StartDocPrinter(IntPtr hPrinter, Int32 level, [In, MarshalAs(UnmanagedType.LPStruct)] DOCINFOA di);
    
     [DllImport("winspool.Drv", EntryPoint = "EndDocPrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     public static extern bool EndDocPrinter(IntPtr hPrinter);
    
     [DllImport("winspool.Drv", EntryPoint = "StartPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     public static extern bool StartPagePrinter(IntPtr hPrinter);
    
     [DllImport("winspool.Drv", EntryPoint = "EndPagePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     public static extern bool EndPagePrinter(IntPtr hPrinter);
    
     [DllImport("winspool.Drv", EntryPoint = "WritePrinter", SetLastError = true, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    
     public static extern bool WritePrinter(IntPtr hPrinter, IntPtr pBytes, Int32 dwCount, out Int32 dwWritten);
    
     
    
     // SendBytesToPrinter()
    
     // When the function is given a printer name and an unmanaged array
    
     // of bytes, the function sends those bytes to the print queue.
    
     // Returns true on success, false on failure.
    
     public static bool SendBytesToPrinter(string szPrinterName, IntPtr pBytes, Int32 dwCount)
    
    {
    
     Int32 dwError = 0, dwWritten = 0;
    
     IntPtr hPrinter = new IntPtr(0);
    
     DOCINFOA di = new DOCINFOA();
    
     bool bSuccess = false; // Assume failure unless you specifically succeed.
    
     di.pDocName = "My C#.NET RAW Document";
    
     di.pDataType = "RAW";
    
     // Open the printer.
    
     //if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
    
     PrinterSettingForPdf objPS = new PrinterSettingForPdf();
    
     PrinterData objPD = new PrinterData();
    
    objPD.Duplex = 1;
    
    objPD.Orientation = 1;
    
     //objPD.Size = 1;
    
     //objPD.Source = 1;
    
     
    
     if (OpenPrinter(szPrinterName.Normalize(), out hPrinter, IntPtr.Zero))
    
    {
    
     // Start a document.
    
     if (StartDocPrinter(hPrinter, 1, di))
    
    {
    
     // Start a page.
    
     if (StartPagePrinter(hPrinter))
    
    {
    
     objPS.ChangePrintersetting(szPrinterName, objPD, 1, false);
    
     // Write your bytes.
    
     bSuccess = WritePrinter(hPrinter, pBytes, dwCount, out dwWritten);
    
    EndPagePrinter(hPrinter);
    
    }
    
    EndDocPrinter(hPrinter);
    
    }
    
     if (hPrinter != IntPtr.Zero)
    
    ClosePrinter(hPrinter);
    
     // ClosePrinter(hPrinter);
    
    }
    
     // If you did not succeed, GetLastError may give more information
    
     // about why not.
    
     if (bSuccess == false)
    
    {
    
     dwError = Marshal.GetLastWin32Error();
    
    }
    
     return bSuccess;
    
    }
    
     public static bool SendFileToPrinter(string szPrinterName, string szFileName)
    
    {
    
     // Open the file.
    
     FileStream fs = new FileStream(szFileName, FileMode.Open);
    
     // Create a BinaryReader on the file.
    
     BinaryReader br = new BinaryReader(fs);
    
     // Dim an array of bytes big enough to hold the file's contents.
    
     Byte[] bytes = new Byte[fs.Length];
    
     bool bSuccess = false;
    
     // Your unmanaged pointer.
    
     IntPtr pUnmanagedBytes = new IntPtr(0);
    
     int nLength;
    
     nLength = Convert.ToInt32(fs.Length);
    
     // Read the contents of the file into the array.
    
    bytes = br.ReadBytes(nLength);
    
     // Allocate some unmanaged memory for those bytes.
    
     pUnmanagedBytes = Marshal.AllocCoTaskMem(nLength);
    
     // Copy the managed byte array into the unmanaged array.
    
     Marshal.Copy(bytes, 0, pUnmanagedBytes, nLength);
    
     // Send the unmanaged bytes to the printer.
    
    bSuccess = SendBytesToPrinter(szPrinterName, pUnmanagedBytes, nLength);
    
     // Free the unmanaged memory that you allocated earlier.
    
     Marshal.FreeCoTaskMem(pUnmanagedBytes);
    
     return bSuccess;
    
    }
    
     public static bool SendStringToPrinter(string szPrinterName, string szString)
    
    {
    
     IntPtr pBytes;
    
     Int32 dwCount;
    
     // How many characters are in the string?
    
    dwCount = szString.Length;
    
     // Assume that the printer is expecting ANSI text, and then convert
    
     // the string to ANSI text.
    
     pBytes = Marshal.StringToCoTaskMemAnsi(szString);
    
     // Send the converted ANSI string to the printer.
    
    SendBytesToPrinter(szPrinterName, pBytes, dwCount);
    
     Marshal.FreeCoTaskMem(pBytes);
    
     return true;
    
    }
    
    }
    
    
    //Class 4: Class that handles printing pdf
    
    public class PrintingPDFData
    
    {
    
    public void SilentPrintPdf(string PdfFileName, string PrinterName)
    
    {
    
     try
    
    {
    
     PrintPdf.SendFileToPrinter(PrinterName, PdfFileName);
    
    }
    
     catch (Exception ex)
    
    {
    
    }
    
    }
    
    }
    
    //类1:该类主要尝试在运行时更改打印机设置
    公共类PrinterSettingForPdf
    {
    #区域“私有变量”
    private IntPtr hPrinter=new System.IntPtr();
    专用打印机_DEFAULTS PrinterValues=新打印机_DEFAULTS();
    专用打印机_INFO_2 pinfo=新打印机_INFO_2();
    //专用打印机_INFO_9 pinfo9=新打印机_INFO_9();
    私有devmodedm;
    私有IntPtr ptrDM;
    私有IntPtr PTRPINTERINFO;
    私有int-sizeOfDevMode=0;
    私有整数错误;
    所需的私人国际单位;
    私人长nRet;
    私人int Interor;
    private System.Int32 nJunk;
    私有IntPtr yDevModeData;
    #端区
    #区域“常数”
    专用常量int DM_双工=0x1000;
    缓冲区中的私有常量int DM_=8;
    私有常量int DM_OUT_BUFFER=2;
    private const int PRINTER_ACCESS_Administrate=0x4;
    私有常量int打印机\u访问\u使用=0x8;
    所需的专用常量int标准权限=0xF0000;
    专用常量int打印机\u所有\u访问=
    (需要标准权限|打印机|访问|管理
    |打印机(访问和使用);
    #端区
    #区域“Win API Def”
    [DllImport(“kernel32.dll”,EntryPoint=“GetLastError”,SetLastError=false,
    ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]
    私有静态外部程序Int32 GetLastError();
    [DllImport(“winspool.Drv”,EntryPoint=“ClosePrinter”,SetLastError=true,
    ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]
    专用静态外部布尔闭合打印机(IntPtr hPrinter);
    [DllImport(“winspool.Drv”,EntryPoint=“DocumentPropertiesA”,SetLastError=true,
    ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]
    专用静态外部int DocumentProperties(IntPtr hwnd、IntPtr hPrinter、,
    [Marshallas(UnmanagedType.LPStr)]字符串pDeviceNameg,
    IntPtr PDEVMODE输出,ref IntPtr PDEVMODE输入,int fMode);
    [DllImport(“winspool.Drv”,EntryPoint=“GetPrinterA”,SetLastError=true,
    CharSet=CharSet.Ansi,ExactSpelling=true,
    CallingConvention=CallingConvention.StdCall)]
    专用静态外部bool GetPrinter(IntPtr hPrinter,Int32 dwLevel,
    IntPtr PPRINT、Int32 dwBuf、out Int32 dwBuf(需要时);
    [DllImport(“winspool.Drv”,EntryPoint=“OpenPrinterA”,
    SetLastError=true,CharSet=CharSet.Ansi,
    ExactSpelling=true,CallingConvention=CallingConvention.StdCall)]
    私有静态外部布尔
    OpenPrinter([Marshallas(UnmanagedType.LPStr)]字符串打印机,
    out IntPtr hPrinter,ref打印机(默认为pd);
    [DllImport(“winspool.drv”,CharSet=CharSet.Ansi,SetLastError=true)]
    专用静态外部布尔设置打印机(IntPtr hPrinter、int级别、IntPtr
    警察总部(int指挥部);
    #端区
    #区域“数据结构”
    [StructLayout(LayoutKind.Sequential)]
    公共结构打印机\u默认值
    {
    公共int-pDatatype;
    公共int PDEV模式;
    公众期望访问;
    }
    [StructLayout(LayoutKind.Sequential)]
    专用结构打印机\u信息\u 2
    {
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串pServerName;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串名称;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串pShareName;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串pPortName;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串名称;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串命令;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串拼音;
    公共IntPtr pDevMode;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串pSepFile;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串处理器;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串pDatatype;
    [Marshallas(UnmanagedType.LPStr)]
    公共字符串参数;
    公共IntPtr pSecurityDescriptor;
    公共Int32属性;
    公共优先权;
    公共优先权;
    公共Int32 StartTime;
    公共Int32时间;
    公共Int32地位;
    公共Int32 CJOB;
    公共Int32平均ppm;
    }
    /// 
    ///打印机信息9结构指定每个用户的默认打印机设置。
    /// 
    /// 
    [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)]
    内部类打印机\u信息\u 9
    {
    /// 
    ///指向定义每个用户的DEVMODE结构的指针
    ///默认打印机数据,如纸张方向和分辨率。
    ///DEVMODE存储在用户的注册表中。
    /// 
    公共IntPtr pDevMode;
    }
    private const short CCDEVICENAME=32;
    private const short CCFORMNAME=32;
    [StructLayout(LayoutKind.Sequential)]
    公共结构DEVMODE
    {
    [Marshallas(UnmanagedType.ByValTStr,SizeConst=CCDEVICENAME)]
    公共字符串dmDeviceName;
    公开短版本;
    公开短讯;
    公开短消息;
    公共短dmDriverExtra;
    公共域;
    公众导向;
    公共短纸张尺寸;
    公共短纸张长度;
    公共短纸张宽度;
    公共短期融资;
    公开短拷贝;
    公共短消息源;
    公共短信息质量;
    公共短彩色;
    公共短双工;
    公共短期债务解决方案;
    公共短期期权;
    公开发行短期票据;
    [Marshallas(UnmanagedType.ByValTStr,