Esempio n. 1
0
 private void cmdResumeJob_Click(object sender, RoutedEventArgs e)
 {
     if (lstJobs.SelectedValue != null)
     {
         PrintQueue         queue = printServer.GetPrintQueue(lstQueues.SelectedValue.ToString());
         PrintSystemJobInfo job   = queue.GetJob((int)lstJobs.SelectedValue);
         job.Resume();
     }
 }
Esempio n. 2
0
        private void cmdCancelJob_Click(object sender, RoutedEventArgs e)
        {
            if (lstJobs.SelectedValue != null)
            {
                PrintQueue         queue = printServer.GetPrintQueue(lstQueues.SelectedValue.ToString());
                PrintSystemJobInfo job   = queue.GetJob((int)lstJobs.SelectedValue);
                job.Cancel();

                lstQueues_SelectionChanged(null, null);
            }
        }
Esempio n. 3
0
        private void lstJobs_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (lstJobs.SelectedValue == null)
            {
                lblJobStatus.Text = "";
            }
            else
            {
                PrintQueue         queue = printServer.GetPrintQueue(lstQueues.SelectedValue.ToString());
                PrintSystemJobInfo job   = queue.GetJob((int)lstJobs.SelectedValue);

                lblJobStatus.Text = "Job Status: " + job.JobStatus.ToString();
            }
        }
Esempio n. 4
0
        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
        }
Esempio n. 5
0
        static void Main(string[] args)
        {
            // Obtain a list of print servers.
            Console.Write("Enter path and file name of CRLF-delimited list of print servers" +
                          "\n(press Return for default \"C:\\PrintServers.txt\"): ");
            String pathToListOfPrintServers = Console.ReadLine();

            if (pathToListOfPrintServers == "")
            {
                pathToListOfPrintServers = @"C:\PrintServers.txt";
            }
            StreamReader fileOfPrintServers = new StreamReader(pathToListOfPrintServers);

            // Obtain the username of the person with the problematic print job.
            Console.Write("\nEnter username of person that submitted print job" +
                          "\n(press Return for the current user {0}: ", Environment.UserName);
            String userName = Console.ReadLine();

            if (userName == "")
            {
                userName = Environment.UserName;
            }

            // Prompt user to determine the method that will be used to read the queue status.
            Console.Write("\nEnter \"Y\" to check the problematic job using its JobStatus attributes." +
                          "\nOtherwise, press Return and the job will be checked using its specific properties: ");
            String useAttributesResponse = Console.ReadLine();

            // Create list of all jobs submitted by user.
            String  line;
            Boolean atLeastOne = false;
            String  jobList    = "\n\nAll print jobs submitted by the user are listed here:\n\n";

            while ((line = fileOfPrintServers.ReadLine()) != null)
            {
                PrintServer          myPS          = new PrintServer(line, PrintSystemDesiredAccess.AdministrateServer);
                PrintQueueCollection myPrintQueues = myPS.GetPrintQueues();

                //<SnippetEnumerateJobsInQueues>
                foreach (PrintQueue pq in myPrintQueues)
                {
                    pq.Refresh();
                    PrintJobInfoCollection jobs = pq.GetPrintJobInfoCollection();
                    foreach (PrintSystemJobInfo job in jobs)
                    {
                        // Since the user may not be able to articulate which job is problematic,
                        // present information about each job the user has submitted.
                        if (job.Submitter == userName)
                        {
                            atLeastOne = true;
                            jobList    = jobList + "\nServer:" + line;
                            jobList    = jobList + "\n\tQueue:" + pq.Name;
                            jobList    = jobList + "\n\tLocation:" + pq.Location;
                            jobList    = jobList + "\n\t\tJob: " + job.JobName + " ID: " + job.JobIdentifier;
                        }
                    } // end for each print job
                }     // end for each print queue
                 //</SnippetEnumerateJobsInQueues>
            }         // end while list of print servers is not yet exhausted

            fileOfPrintServers.Close();

            if (!atLeastOne)
            {
                jobList = "\n\nNo jobs submitted by " + userName + " were found.\n\n";
                Console.WriteLine(jobList);
            }
            else
            {
                jobList = jobList + "\n\nIf multiple jobs are listed, use the information provided" +
                          " above and by the user to identify the job needing diagnosis.\n\n";
                Console.WriteLine(jobList);
                //<SnippetIdentifyAndDiagnoseProblematicJob>
                // When the problematic print job has been identified, enter information about it.
                Console.Write("\nEnter the print server hosting the job (including leading slashes \\\\): " +
                              "\n(press Return for the current computer \\\\{0}): ", Environment.MachineName);
                String pServer = Console.ReadLine();
                if (pServer == "")
                {
                    pServer = "\\\\" + Environment.MachineName;
                }
                Console.Write("\nEnter the print queue hosting the job: ");
                String pQueue = Console.ReadLine();
                Console.Write("\nEnter the job ID: ");
                Int16 jobID = Convert.ToInt16(Console.ReadLine());

                // Create objects to represent the server, queue, and print job.
                PrintServer        hostingServer = new PrintServer(pServer, PrintSystemDesiredAccess.AdministrateServer);
                PrintQueue         hostingQueue  = new PrintQueue(hostingServer, pQueue, PrintSystemDesiredAccess.AdministratePrinter);
                PrintSystemJobInfo theJob        = hostingQueue.GetJob(jobID);

                if (useAttributesResponse == "Y")
                {
                    TroubleSpotter.SpotTroubleUsingJobAttributes(theJob);
                    // TroubleSpotter class is defined in the complete example.
                }
                else
                {
                    TroubleSpotter.SpotTroubleUsingProperties(theJob);
                }

                TroubleSpotter.ReportQueueAndJobAvailability(theJob);
                //</SnippetIdentifyAndDiagnoseProblematicJob>
            }// end else at least one job was submitted by user

            // End the program
            Console.WriteLine("\nPress Return to end.");
            Console.ReadLine();
        } // end Main
        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
        }
Esempio n. 7
0
        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
            // 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

            // Iterate through all elements in the data array
            for (int i = 0; i < data.Length; 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)
                        {
                            if ((jStatus & JOBSTATUS.JOB_STATUS_DELETING) == JOBSTATUS.JOB_STATUS_DELETING
                                &&
                                (jStatus & JOBSTATUS.JOB_STATUS_PRINTING) == JOBSTATUS.JOB_STATUS_PRINTING
                                &&
                                (jStatus & JOBSTATUS.JOB_STATUS_PRINTED) == JOBSTATUS.JOB_STATUS_PRINTED)
                            {
                                if (intJobID != _lastJobID)
                                {
                                    // Raise the event
                                    OnJobStatusChange(this, new PrintJobChangeEventArgs(intJobID, strJobName, jStatus, pji));
                                    _lastJobID = intJobID;
                                }
                            }
                        }
                    }
                }
            }
            // Reset the Event and wait for the next event
            _mrEvent.Reset();
            _waitHandle = ThreadPool.RegisterWaitForSingleObject(_mrEvent, new WaitOrTimerCallback(PrinterNotifyWaitCallback), _mrEvent, -1, true);
        }
        /** \brief Detalles del Trabajo de Impresion
         *  \param Printer Nombre de impresora
         *  \param JobId Número de trabajo de impresión
         *  \param PrintJob Estructura para almacenar las propiedades del trabajo de impresión, pasado por referencia
         *  \details
         * Con este método recuperamos los detalles del trabajo de impresión: Cola, Número de Páginas, Tamaño página, Usuario, etc.
         *  \remarks Hay que revisar si la propiedad PrintQueue.IsRawOnlyEnabled = False indica que el spool del trabajo
         *  se almacena en formato EMF.
         */
        public static void DetailsPrint(string Printer, string JobId, ref STRUCT_PRINT_JOB PrintJob)
        {
            PrintQueue         ColaImpresion = null;
            PrintSystemJobInfo JobInfo       = null;

            Log.Debug("=========================================================================");
            Log.Debug("                        NAMESPACE System.Printing");
            Log.Debug("=========================================================================");
            Log.Debug("");

            /// Conectamos con el Servidor de impresión local
            LocalPrintServer ServidorImpresionLocal = null;

            try
            {
                ServidorImpresionLocal = new LocalPrintServer();
                Log.Debug("==> Servidor de Impresión: " + ServidorImpresionLocal.Name);
            }
            catch (Exception e)
            {
                Log.Error("No se puede abrir el Servidor de Impresión Local: " + e);
                throw e;
            }

            /// Abrimos la impresora y su trabajo de Impresión pasados como argumentos al método
            Log.Debug("==> Trabajo de impresión: " + JobId + " a través de la  Cola de Impresión: " + Printer);
            try
            {
                Log.Debug("Abrimos conexión con impresora: " + Printer);
                ColaImpresion = (PrintQueue)ServidorImpresionLocal.GetPrintQueue(Printer);
                Log.Debug("Recuperamos trabajo de Impresión: " + JobId);
                ColaImpresion.GetJob(Convert.ToInt32(JobId));
                ColaImpresion.Refresh();

                /// - Generamos log con las propiedades del Trabajo de Impresión
                if (ColaImpresion.IsRawOnlyEnabled)
                {
                    Log.Debug("==> La cola de impresión sólo utiliza RAW.");
                }
                else
                {
                    Log.Debug("==> La cola de impresión admite EMF.");
                }

                /// Se guarda en el log los detalles del trabajo de impresión
                Log.Debug("PageMediaSizeName: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize.PageMediaSizeName);
                Log.Debug("PageMediaSize: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize);
                Log.Debug("Width: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize.Width);
                Log.Debug("Height: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize.Height);
                Log.Debug("Número copias: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.CopyCount);
                Log.Debug("OutputColor: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.OutputColor);
                Log.Debug("PageOrientation: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageOrientation);
                Log.Debug("Duplexing: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.Duplexing);
                Log.Debug("OutputColor: " + ColaImpresion.CurrentJobSettings.CurrentPrintTicket.OutputColor);
                Log.Debug("=====>  Propiedades JOB a través PrintSystemJobInfoFO  ====");
                JobInfo = PrintSystemJobInfo.Get(ColaImpresion, Convert.ToInt32(JobId));
                Log.Debug("JobStatus: " + JobInfo.JobStatus);
                Log.Debug("Name: " + JobInfo.Name);
                Log.Debug("NumberOfPages: " + JobInfo.NumberOfPages);
                Log.Debug("NumberOfPagesPrinted: " + JobInfo.NumberOfPagesPrinted);
                Log.Debug("Submitter: " + JobInfo.Submitter);
                Log.Debug("TimeJobSubmitted: " + JobInfo.TimeJobSubmitted.ToString());
                Log.Debug("JobSize: " + JobInfo.JobSize);

                /// - Almacenamos las propiedades del Trabajo de Impresión en el struct de entrada al método pasado por referencia
                PrintJob.F_PRINTJOB = JobInfo.TimeJobSubmitted.ToLocalTime().Day.ToString().PadLeft(2, '0') + "/" +
                                      JobInfo.TimeJobSubmitted.ToLocalTime().Month.ToString().PadLeft(2, '0') + "/" +
                                      JobInfo.TimeJobSubmitted.ToLocalTime().Year.ToString().PadLeft(4, '0') + " " +
                                      JobInfo.TimeJobSubmitted.ToLocalTime().Hour.ToString().PadLeft(2, '0') + ":" +
                                      JobInfo.TimeJobSubmitted.ToLocalTime().Minute.ToString().PadLeft(2, '0') + ":" +
                                      JobInfo.TimeJobSubmitted.ToLocalTime().Second.ToString().PadLeft(2, '0');
                PrintJob.ID_JOBNAME      = PrintJob.N_JOB.ToString().PadLeft(5, '0') + "_" + PrintJob.F_PRINTJOB;
                PrintJob.ID_FUENTE       = "System.Printing";
                PrintJob.ID_LOGIN        = JobInfo.Submitter;
                PrintJob.ID_PRINTSERVER  = ServidorImpresionLocal.Name;
                PrintJob.ID_DOCUMENT     = JobInfo.Name;
                PrintJob.N_PAGES         = JobInfo.NumberOfPages;
                PrintJob.N_PAGES_PRINTED = JobInfo.NumberOfPagesPrinted;
                PrintJob.N_LENGTH        = (int)ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize.Height;
                PrintJob.N_WIDTH         = (int)ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize.Width;

                PrintJob.ID_MEDIASIZE   = ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize.ToString(); // PageMediaSizeName;
                PrintJob.N_MEDIASIZE    = (int)ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageMediaSize.PageMediaSizeName;
                PrintJob.N_ORIENTATION  = (int)ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageOrientation;
                PrintJob.ID_ORIENTATION = ColaImpresion.CurrentJobSettings.CurrentPrintTicket.PageOrientation.ToString();
                PrintJob.N_COPIES       = (int)ColaImpresion.CurrentJobSettings.CurrentPrintTicket.CopyCount;
                PrintJob.ID_COLOR       = ColaImpresion.CurrentJobSettings.CurrentPrintTicket.OutputColor.ToString();
                PrintJob.N_COLOR        = (int)ColaImpresion.CurrentJobSettings.CurrentPrintTicket.OutputColor;
                PrintJob.ID_DUPLEX      = ColaImpresion.CurrentJobSettings.CurrentPrintTicket.Duplexing.ToString();
                if (ColaImpresion.CurrentJobSettings.CurrentPrintTicket.Duplexing != null)
                {
                    PrintJob.N_DUPLEX = (int)ColaImpresion.CurrentJobSettings.CurrentPrintTicket.Duplexing;
                }
                PrintJob.ID_STATUS = JobInfo.JobStatus.ToString();
                // ?: Operador condicional ==> (condicion) ? valor_caso_verdadero : valor_caso_falso
                PrintJob.N_COLORPAGES = (PrintJob.ID_COLOR.ToUpper() == "COLOR") ?  PrintJob.N_PAGES_PRINTED: 0;
                PrintJob.N_JOBSIZE    = JobInfo.JobSize;
            }
            catch (Exception e)
            {
                Log.Error("No se puede abrir el trabajo de impresión: " + JobId + " a través de la  Cola de Impresión: " + Printer);
                Log.Fatal("Comprobar que en la impresora: " + Printer + " se guardan los trabajos de impresión", e);
                throw e;
            }
        } // Fin DetailsPrint()
        internal void PrinterNotifyWaitCallback(object state, bool timedOut)
        {
            if (_printerHandle == IntPtr.Zero)
            {
                return;
            }


            _notifyOptions.Count = 1;
            int  pdwChange   = 0;
            var  pNotifyInfo = IntPtr.Zero;
            bool bResult     = FindNextPrinterChangeNotification(_changeHandle, out pdwChange, _notifyOptions,
                                                                 ref pNotifyInfo);

            if (bResult == false || pNotifyInfo == IntPtr.Zero)
            {
                return;
            }


            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;
            }


            var  info  = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO));
            long 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));
            }


            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
                    )
                {
                    var                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
                    {
                        //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));
                    }
                }
            }


            _mrEvent.Reset();
            _waitHandle =
                ThreadPool.RegisterWaitForSingleObject(_mrEvent, PrinterNotifyWaitCallback, _mrEvent, -1, true);
        }
        /// <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
        }