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 }
internal void PrinterNotifyWaitCallback(object state, bool timedOut) { if (_printerHandle == IntPtr.Zero) { return; } #region read notification details _notifyOptions.Count = 1; var pdwChange = 0; IntPtr pNotifyInfo; var 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 var 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 var info = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO)); var pData = (long)pNotifyInfo + (long)Marshal.OffsetOf(typeof(PRINTER_NOTIFY_INFO), "aData"); var 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 (var i = 0; i < data.Count(); i++) { if ((data[i].Field == (ushort)PRINTERJOBNOTIFICATIONTYPES.JOB_NOTIFY_FIELD_STATUS) && (data[i].Type == (ushort)PRINTERNOTIFICATIONTYPES.JOB_NOTIFY_TYPE) ) { var jStatus = (JOBSTATUS)Enum.Parse(typeof(JOBSTATUS), data[i].NotifyData.Data.cbBuf.ToString()); var 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 { //Trace.WriteLine(ex.Message); pji = null; _objJobDict.TryGetValue(intJobId, out strJobName); if (strJobName == null) { strJobName = string.Empty; } } 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, PrinterNotifyWaitCallback, _mrEvent, -1, true); #endregion }
/// <summary> /// Отлавливается нужное задание и вызывается событие, на которое подписались в вызывающем коде /// </summary> /// <param name="state"></param> /// <param name="timedOut"></param> internal void PrinterNotifyWaitCallback(object state, bool timedOut) { if (_printerHandle == IntPtr.Zero) { return; } #region read notification details _notifyOptions.Count = 1; var pdwChange = 0; IntPtr pNotifyInfo; var bResult = FindNextPrinterChangeNotification(_changeHandle, out pdwChange, _notifyOptions, out pNotifyInfo); _notifyOptions.dwFlags = 0; //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 var 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 var info = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO)); var pData = (long)pNotifyInfo + (long)Marshal.OffsetOf(typeof(PRINTER_NOTIFY_INFO), "aData"); var 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 (var i = 0; i < data.Count(); i++) { if (data[i].Field == (ushort)PRINTERJOBNOTIFICATIONTYPES.JOB_NOTIFY_FIELD_STATUS && (data[i].Type == (ushort)PRINTERNOTIFICATIONTYPES.JOB_NOTIFY_TYPE || data[i].Type == (ushort)PRINTERJOBNOTIFICATIONTYPES.JOB_NOTIFY_FIELD_TOTAL_PAGES) ) { var jStatus = (JOBSTATUS)Enum.Parse(typeof(JOBSTATUS), data[i].NotifyData.Data.cbBuf.ToString()); if ((jStatus & JOBSTATUS.JOB_STATUS_DELETING) != 0 || (jStatus & JOBSTATUS.JOB_STATUS_DELETED) != 0 || (jStatus & JOBSTATUS.JOB_STATUS_ERROR) != 0) { return; } var 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] = $"'n:{pji.Name}|js:{pji.JobStatus}|pn:{pji.NumberOfPages}|ji:{intJobId}|{Guid.NewGuid().ToString()}'"; } strJobName = pji.Name; pji.Refresh(); } catch (Exception ex) { pji = null; _objJobDict.TryGetValue(intJobId, out strJobName); if (strJobName == null) { strJobName = string.Empty; } Registry.GetValue <Logger>().Error(ex, "When extract job"); return; } if (OnJobStatusChange != null) { //Let us raise the event calls: pqm_OnJobStatusChange JobDetail jobDetails = GetJobDetail(data[i].Id); //Get detalis about job OnJobStatusChange(this, new PrintJobChangeEventArgs(intJobId, _objJobDict[intJobId], strJobName, jStatus, jobDetails, pji)); //Set pause for job } } } #endregion #region reset the Event and wait for the next event _mrEvent.Reset(); _waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, PrinterNotifyWaitCallback, _mrEvent, -1, true); #endregion }