public void PrinterNotifyWaitCallback(Object state, bool timedOut) { if (_printerHandle == IntPtr.Zero) { return; } #region read notification details _notifyOptions.Count = 1; int pdwChange = 0; IntPtr pNotifyInfo = IntPtr.Zero; bool bResult = FindNextPrinterChangeNotification(_changeHandle, out pdwChange, _notifyOptions, out pNotifyInfo); //If the Printer Change Notification Call did not give data, exit code if ((bResult == false) || (((int)pNotifyInfo) == 0)) { return; } //If the Change Notification was not relgated to job, exit code bool bJobRelatedChange = ((pdwChange & PRINTER_CHANGES.PRINTER_CHANGE_ADD_JOB) == PRINTER_CHANGES.PRINTER_CHANGE_ADD_JOB) || ((pdwChange & PRINTER_CHANGES.PRINTER_CHANGE_SET_JOB) == PRINTER_CHANGES.PRINTER_CHANGE_SET_JOB) || ((pdwChange & PRINTER_CHANGES.PRINTER_CHANGE_DELETE_JOB) == PRINTER_CHANGES.PRINTER_CHANGE_DELETE_JOB) || ((pdwChange & PRINTER_CHANGES.PRINTER_CHANGE_WRITE_JOB) == PRINTER_CHANGES.PRINTER_CHANGE_WRITE_JOB); if (!bJobRelatedChange) { return; } #endregion #region populate Notification Information //Now, let us initialize and populate the Notify Info data PRINTER_NOTIFY_INFO info = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO)); int pData = (int)pNotifyInfo + Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO)); PRINTER_NOTIFY_INFO_DATA[] data = new PRINTER_NOTIFY_INFO_DATA[info.Count]; for (uint i = 0; i < info.Count; i++) { data[i] = (PRINTER_NOTIFY_INFO_DATA)Marshal.PtrToStructure((IntPtr)pData, typeof(PRINTER_NOTIFY_INFO_DATA)); pData += Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO_DATA)); } #endregion #region iterate through all elements in the data array for (int i = 0; i < data.Count(); i++) { if ((data[i].Field == (ushort)PRINTERJOBNOTIFICATIONTYPES.JOB_NOTIFY_FIELD_STATUS) && (data[i].Type == (ushort)PRINTERNOTIFICATIONTYPES.JOB_NOTIFY_TYPE) ) { JOBSTATUS jStatus = (JOBSTATUS)Enum.Parse(typeof(JOBSTATUS), data[i].NotifyData.Data.cbBuf.ToString()); int intJobID = (int)data[i].Id; string strJobName = ""; PrintSystemJobInfo pji = null; try { _spooler = new PrintQueue(new PrintServer(), _spoolerName); pji = _spooler.GetJob(intJobID); if (!objJobDict.ContainsKey(intJobID)) { objJobDict[intJobID] = pji.Name; } strJobName = pji.Name; } catch { pji = null; objJobDict.TryGetValue(intJobID, out strJobName); if (strJobName == null) { strJobName = ""; } } if (OnJobStatusChange != null) { //Let us raise the event OnJobStatusChange(this, new PrintJobChangeEventArgs(intJobID, strJobName, jStatus, pji)); } } } #endregion #region reset the Event and wait for the next event _mrEvent.Reset(); _waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true); #endregion }
public void PrinterNotifyWaitCallback(Object state, bool timedOut) { ManualResetEvent Mevent = (ManualResetEvent)state; PrinterModel printerModel = printerModels.FirstOrDefault(o => o.ChangeHandle == Mevent.Handle); #region read notification details printerModel.NotifyOptions.Count = 1; int pdwChange = 0; IntPtr pNotifyInfo = IntPtr.Zero; bool bResult = FindNextPrinterChangeNotification(printerModel.ChangeHandle, out pdwChange, printerModel.NotifyOptions, out pNotifyInfo); if ((bResult == false) || (((long)pNotifyInfo) == 0)) { return; } bool bJobRelatedChange = pdwChange > 0; if (!bJobRelatedChange) { return; } #endregion #region populate Notification Information PRINTER_NOTIFY_INFO info = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO)); long pData = (long)pNotifyInfo + (long)Marshal.OffsetOf(typeof(PRINTER_NOTIFY_INFO), "aData"); PRINTER_NOTIFY_INFO_DATA[] data = new PRINTER_NOTIFY_INFO_DATA[info.Count]; for (uint i = 0; i < info.Count; i++) { data[i] = (PRINTER_NOTIFY_INFO_DATA)Marshal.PtrToStructure((IntPtr)pData, typeof(PRINTER_NOTIFY_INFO_DATA)); pData += Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO_DATA)); } #endregion #region iterate through all elements in the data array for (int i = 0; i < data.Count(); i++) { if ((data[i].Field == (ushort)PRINTERJOBNOTIFICATIONTYPES.JOB_NOTIFY_FIELD_STATUS) && (data[i].Type == (ushort)PRINTERNOTIFICATIONTYPES.JOB_NOTIFY_TYPE)) { JOBSTATUS jStatus = (JOBSTATUS)Enum.Parse(typeof(JOBSTATUS), data[i].NotifyData.Data.cbBuf.ToString()); int intJobID = (int)data[i].Id; string strJobName = ""; PrintSystemJobInfo pji = null; short shortJobCopies = 1; uint uintJobTotalPages = 1; try { printerModel.Spooler = new PrintQueue(new PrintServer(), printerModel.PrinterName); pji = printerModel.Spooler.GetJob(intJobID); if (!objJobDict.ContainsKey(intJobID)) { objJobDict[intJobID] = pji.Name; } strJobName = pji.Name; GetJob(printerModel.PrinterHandle, (uint)intJobID, 2, IntPtr.Zero, 0, out uint needed); if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER) { IntPtr buffer = Marshal.AllocHGlobal((int)needed); GetJob(printerModel.PrinterHandle, (uint)intJobID, 2, buffer, needed, out needed); JOB_INFO_2 jobInfo = (JOB_INFO_2)Marshal.PtrToStructure(buffer, typeof(JOB_INFO_2)); DEVMODE dMode = (DEVMODE)Marshal.PtrToStructure(jobInfo.pDevMode, typeof(DEVMODE)); shortJobCopies = dMode.dmCopies; uintJobTotalPages = jobInfo.TotalPages; Marshal.FreeHGlobal(buffer); } } catch { pji = null; objJobDict.TryGetValue(intJobID, out strJobName); if (strJobName == null) { strJobName = ""; } } OnJobStatusChange?.Invoke(this, new PrintJobChangeEventArgs(intJobID, strJobName, jStatus, pji, uintJobTotalPages, shortJobCopies)); } } #endregion #region reset the Event and wait for the next event try { printerModel.MrEvent.Reset(); printerModel.WaitHandle = ThreadPool.RegisterWaitForSingleObject(printerModel.MrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), printerModel.MrEvent, -1, true); } catch { } #endregion }
public static extern bool FreePrinterNotifyInfo([In] ref PRINTER_NOTIFY_INFO pPrinterNotifyInfo);