/* System.Printing.dll * MS.Internal.PrintWin32Thunk.PrinterThunkHandler.ThunkEnumPrinters(); * * System.Drawing.dll: * System.Drawing.Printing.PrinterSettings.InstalledPrinters.Get; */ internal static object[] ThunkEnumPrinters(PrinterFlags flags, string name, int level) { Type type = null; switch (level) { case 1: type = typeof(PrinterInfo1); break; case 2: type = typeof(PrinterInfo2); break; case 4: type = typeof(PrinterInfo4); break; case 5: type = typeof(PrinterInfo5); break; default: throw Error.ArgumentOutOfRange("level"); } // 所需缓存字节数量 int pcbNeeded; // 数据条目数量 int pcReturned; // 首次调用 为了获知: 所需缓存字节数量 if (!EnumPrinters(flags, name, level, IntPtr.Zero, 0, out pcbNeeded, out pcReturned)) { Error.ThrowIfLastErrorIsNotInsufficientBuffer(); } if (pcbNeeded > 0) { var pBuffer = IntPtr.Zero; try { // 分配本地内存 pBuffer = Marshal.AllocHGlobal(pcbNeeded); if (!EnumPrinters(flags, name, level, pBuffer, pcbNeeded, out pcbNeeded, out pcReturned)) { Error.ThrowLastError(); } var p = pBuffer; // 当前数据起始指针 var size = Marshal.SizeOf(type); // 单个数据指针增量 var infos = new object[pcReturned]; for (int i = 0; i < pcReturned; i++) { infos[i] = Marshal.PtrToStructure(p, type); p += size; } return(infos); } finally { // 释放本地内存 if (pBuffer != IntPtr.Zero) { Marshal.FreeHGlobal(pBuffer); } } } return(new object[0]); }
static extern bool EnumPrinters(PrinterFlags Flags, string Name, int Level, IntPtr pPrinterEnum, int cbBuf, out int pcbNeeded, out int pcReturned);