public void Start() { if (!WinSpool.OpenPrinter(printerName, out hPrinter, IntPtr.Zero)) { var errorCode = Marshal.GetLastWin32Error(); throw new SpoolWatcherException($"Error in OpenPrinter: {errorCode}"); } var printerNotifyOptions = new PrinterNotifyOptions(); printerNotifyOptions.Version = 2; var optionsType = CreateOptionsType(); printerNotifyOptions.Count = (uint)optionsType.Count(); var pNotifyOptionsSz = Marshal.SizeOf <PrinterNotifyOptions>(); printerNotifyOptions.pTypes = Marshal.AllocHGlobal(pNotifyOptionsSz * optionsType.Count()); for (int i = 0; i < optionsType.Count(); i++) { var ptr = IntPtr.Add(printerNotifyOptions.pTypes, i * pNotifyOptionsSz); Marshal.StructureToPtr(optionsType.ElementAt(i), ptr, false); } notificationHandle = WinSpool.FindFirstPrinterChangeNotification(hPrinter, PrinterChange, (uint)printerNotifyCategory, ref printerNotifyOptions); foreach (var optionType in optionsType) { Marshal.FreeHGlobal(optionType.pFields); } Marshal.FreeHGlobal(printerNotifyOptions.pTypes); if (notificationHandle.IsInvalid) { var errorCode = Marshal.GetLastWin32Error(); throw new SpoolWatcherException($"Error in FindFirstPrinterChangeNotification: {errorCode}"); } stopEvent.Reset(); tNotifications = new Thread(() => WaitForNotifications()); tNotifications.Start(); }
internal static extern bool FindNextPrinterChangeNotification(SafeNotificationHandle hChange, out PrinterChange pdwChange, PrinterNotifyOptions printerNotifyOptions, out SafePrinterNotifyInfo pPrinterNotifyInfo);
private void WaitForNotifications() { var handles = new WaitHandle[] { notificationHandle, stopEvent.WaitHandle }; while (WaitHandle.WaitAny(handles) == 0) { if (WinSpool.FindNextPrinterChangeNotification(notificationHandle, out var change, IntPtr.Zero, out SafePrinterNotifyInfo pNotifyInfo)) { PrinterNotifyInfo printerNotifyInfo = pNotifyInfo; while ((printerNotifyInfo.Flags & PRINTER_NOTIFY_INFO_DISCARDED) == PRINTER_NOTIFY_INFO_DISCARDED) { pNotifyInfo.Close(); var notifyOptions = new PrinterNotifyOptions { Flags = PRINTER_NOTIFY_OPTIONS_REFRESH }; var nextRet = WinSpool.FindNextPrinterChangeNotification(notificationHandle, out change, notifyOptions, out pNotifyInfo); printerNotifyInfo = pNotifyInfo; if (!nextRet) { break; } } if (SpoolerNotificationReached != null) { var datas = new List <NotificationInfo>(); for (uint i = 0; i < printerNotifyInfo.Count; i++) { var notificationInfo = new NotificationInfo(); notificationInfo.Id = printerNotifyInfo.aData[i].Id; switch (printerNotifyInfo.aData[i].Type) { case NotifyType.Job: notificationInfo.Type = NotifyType.Job; notificationInfo.InfoData = DataFieldParser.GetJobTypeData(printerNotifyInfo.aData[i]); break; case NotifyType.Printer: notificationInfo.Type = NotifyType.Printer; notificationInfo.InfoData = DataFieldParser.GetPrinterTypeData(printerNotifyInfo.aData[i]); break; default: break; } datas.Add(notificationInfo); } var evArgs = new SpoolNotificationEventArgs { PrinterChange = change, NotificationInfos = datas.ToArray() }; SpoolerNotificationReached(this, evArgs); } pNotifyInfo.Close(); } } }
internal static extern SafeNotificationHandle FindFirstPrinterChangeNotification(SafeHPrinter hPrinter, PrinterChange fdwFlags, uint fdwOptions, ref PrinterNotifyOptions pPrinterNotifyOptions);