public static IChangeNotification Create(PRINTER_CHANGE changes, string printerName = null, PRINTER_NOTIFY_CATEGORY category = PRINTER_NOTIFY_CATEGORY.PRINTER_NOTIFY_CATEGORY_ALL, NotifyOptions options = null) { var notification = new ChangeNotification { _printerHandle = OpenPrinter(printerName) }; var ptrNotifyOptions = IntPtr.Zero; try { if (options != null) { var size = SizeOfNotifyOptions(options); ptrNotifyOptions = Marshal.AllocHGlobal(size); ToPtr(ptrNotifyOptions, options); } notification._changeHandle = NativeMethods.FindFirstPrinterChangeNotification( notification._printerHandle, (UInt32)changes, (UInt32)category, ptrNotifyOptions); if (notification._changeHandle == INVALID_HANDLE_VALUE) { throw new Win32Exception(); } // Don't let SafeWaitHandle own the handle as it can't close it notification.SafeWaitHandle = new SafeWaitHandle(notification._changeHandle, false); } catch { NativeMethods.ClosePrinter(notification._printerHandle); throw; } finally { Marshal.FreeHGlobal(ptrNotifyOptions); } return(notification); }
private static void MonitorPrinter(string printerName, NotifyOptions printerNotifyOptions, PRINTER_CHANGE change) { if (printerNotifyOptions == null && change == 0) { throw new Exception("Either or both of printer changes or fields to monitor must be set."); } using var printerChangeNotification = ChangeNotification.Create(change, printerName, PRINTER_NOTIFY_CATEGORY.PRINTER_NOTIFY_CATEGORY_ALL, printerNotifyOptions); while (true) { printerChangeNotification.WaitHandle.WaitOne(); NotifyInfo printerNotifyInfo; bool refresh = false; do { printerNotifyInfo = printerChangeNotification.FindNextPrinterChangeNotification(refresh); WriteToConsole(printerNotifyInfo); refresh = true; // For next iteration if data overflowed } while ((printerNotifyInfo.Flags & NotifyInfo.PRINTER_NOTIFY_INFO_DISCARDED) != 0); } }