首先我们看看EnumPrinters函数的定义

BOOL EnumPrinters(
 DWORD Flags, // printer object types
 LPTSTR Name, // name of printer object
 DWORD Level, // information level
 LPBYTE pPrinterEnum, // printer information buffer
 DWORD cbBuf, // size of printer information buffer
 LPDWORD pcbNeeded, // bytes received or required
 LPDWORD pcReturned // number of printers enumerated
 );


这个api有几个返回参数, 其中最重要的是pPrinterEnum所指的缓冲区中,是一个
PRINTER_INFO_N的结构数组, 这里N根据Level参数而变化, 这里我们用的是1, 所以用到的结构是

typedef struct _PRINTER_INFO_1 { 
 DWORD Flags; 
 LPTSTR pDescription; 
 LPTSTR pName; 
 LPTSTR pComment; 
 } PRINTER_INFO_1

C#要调用API首先要引入动态库,EnumPrinters在winspool.drv这个动态库中。引入语句如下

[DllImport("winspool.drv", CharSet=CharSet.Auto)]
 然后是定义PRINTER_INFO_1结构
 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
 struct PRINTER_INFO_1
 {
 int flags;
 [MarshalAs(UnmanagedType.LPTStr)]
 public string pDescription;
 [MarshalAs(UnmanagedType.LPTStr)]
 public string pName;
 [MarshalAs(UnmanagedType.LPTStr)]
 public string pComment;
 }


好了,全部的源代码如下:

using System;
 using System.Collections;
 using System.Runtime.InteropServices;
 using System.Diagnostics;
 using System.Drawing.Printing;
 public class QuickTest {
 [DllImport("winspool.drv", CharSet=CharSet.Auto)]
 static extern bool EnumPrinters(int flags, string name, int level, IntPtr pPrinterEnum,
 int cbBuf, out int pcbNeeded, out int pcReturned);private const int PRINTER_ENUM_NETWORK = 0x00000040;
 private const int PRINTER_ENUM_LOCAL = 0x00000002;
 private const int PRINTER_ENUM_REMOTE = 0x00000010;
 [StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
 struct PRINTER_INFO_1
 {
 int flags;
 [MarshalAs(UnmanagedType.LPTStr)]
 public string pDescription;
 [MarshalAs(UnmanagedType.LPTStr)]
 public string pName;
 [MarshalAs(UnmanagedType.LPTStr)]
 public string pComment;
 }public void EnumeratePrintersWin() 
 {
 bool Success;
 int cbRequired;
 int nEntries;IntPtr outb = IntPtr.Zero;
Success = EnumPrinters(PRINTER_ENUM_NETWORK | PRINTER_ENUM_LOCAL | PRINTER_ENUM_REMOTE, null , 1, outb, 0, out cbRequired, out nEntries);
 outb = Marshal.AllocHGlobal(cbRequired);
 Success = EnumPrinters(PRINTER_ENUM_NETWORK | PRINTER_ENUM_LOCAL | PRINTER_ENUM_REMOTE, null , 1, outb, cbRequired, out cbRequired, out nEntries);PRINTER_INFO_1[] portsArray = new PRINTER_INFO_1[cbRequired];
 IntPtr current = outb;
 try {
 for (int i=0; i<portsArray.Length; i++)
 {
 portsArray[i] = (PRINTER_INFO_1) Marshal.PtrToStructure(current,
 typeof(PRINTER_INFO_1));
 current=(IntPtr)((int)current+Marshal.SizeOf(typeof(PRINTER_INFO_1)));
 Console.WriteLine(i+": \n"+portsArray[i].pName+"\n"+portsArray[i].pDescription+"\n"+portsArray[i].pComment+"\n");
 } 
 }
 catch (Exception) {
 //Console.WriteLine(exp.StackTrace);
 }
 Marshal.FreeHGlobal(outb);
 }
 public QuickTest () {}
 public static void Main() {
 QuickTest qt = new QuickTest();
 qt.EnumeratePrintersWin();
 }
 }