/** \brief inicializa las propiedades del Trabajo de Impresión * \param PrintJob Estructura con las propiedades del trabjao de impresión */ private void LimpiaStrucPrintJob(ref STRUCT_PRINT_JOB PrintJob) //public static void LimpiaStrucPrintJob(ref STRUCT_PRINT_JOB PrintJob) { Log.Debug("Se Inicializa STRUCT_PRINT_JOB PrintJob"); PrintJob.ID_JOBNAME = this.ID_JOBNAME; PrintJob.ID_FUENTE = ""; PrintJob.N_JOB = this.N_JOB; PrintJob.ID_PRINTER = this.ID_PRINTER; PrintJob.N_PAGES = 0; PrintJob.N_PAGES_PRINTED = 0; PrintJob.N_COLORPAGES = 0; PrintJob.N_LENGTH = 0; PrintJob.N_WIDTH = 0; PrintJob.ID_MEDIASIZE = ""; PrintJob.N_MEDIASIZE = -1; PrintJob.ID_ORIENTATION = ""; PrintJob.N_ORIENTATION = -1; PrintJob.N_COLOR = -1; PrintJob.ID_DUPLEX = ""; PrintJob.N_DUPLEX = -1; PrintJob.N_COPIES = 0; PrintJob.ID_STATUS = ""; PrintJob.ID_MEDIATYPE = ""; PrintJob.N_MEDIATYPE = 0; } //LimpiaStrucPrintJob()
} //GuardarLog() /** \brief Log del trabajo de impresión */ public static void LogPrintJob(ref STRUCT_PRINT_JOB PrintJob) { /// Generamos log con las propiedades del trabajo de impresión Log.Info("ID_JOBNAME: " + PrintJob.ID_JOBNAME); Log.Info("ID_FUENTE: " + PrintJob.ID_FUENTE); Log.Info("N_JOB: " + PrintJob.N_JOB); Log.Info("F_PRINTJOB: " + PrintJob.F_PRINTJOB); Log.Info("ID_LOGIN: "******"ID_PRINTSERVER: " + PrintJob.ID_PRINTSERVER); Log.Info("ID_PRINTER: " + PrintJob.ID_PRINTER); Log.Info("ID_DOCUMENT: " + PrintJob.ID_DOCUMENT); Log.Info("N_PAGES: " + PrintJob.N_PAGES); Log.Info("N_PAGES_PRINTED: " + PrintJob.N_PAGES_PRINTED); Log.Info("N_COLORPAGES: " + PrintJob.N_COLORPAGES); Log.Info("N_LENGTH: " + PrintJob.N_LENGTH); Log.Info("N_WIDTH: " + PrintJob.N_WIDTH); Log.Info("ID_MEDIASIZE: " + PrintJob.ID_MEDIASIZE); Log.Info("N_MEDIASIZE: " + PrintJob.N_MEDIASIZE); Log.Info("ID_ORIENTATION: " + PrintJob.ID_ORIENTATION); Log.Info("N_ORIENTATION: " + PrintJob.N_ORIENTATION); Log.Info("N_COPIES: " + PrintJob.N_COPIES); Log.Info("ID_COLOR: " + PrintJob.ID_COLOR); Log.Info("N_COLOR: " + PrintJob.N_COLOR); Log.Info("ID_DUPLEX: " + PrintJob.ID_DUPLEX); Log.Info("N_DUPLEX: " + PrintJob.N_DUPLEX); Log.Info("ID_STATUS: " + PrintJob.ID_STATUS); Log.Info("ID_ISPLOTTER: " + PrintJob.ID_ISPLOTTER); Log.Info("ID_MEDIATYPE: " + PrintJob.ID_MEDIATYPE); Log.Info("N_MEDIATYPE: " + PrintJob.N_MEDIATYPE); Log.Info("N_JOBSIZE: " + PrintJob.N_JOBSIZE); }
} // LeerDevmode /** \brief Lectura registro EmrHeader * \details Lectura y analisis registro EMR_HEADER, Su estructura se define en el documento MS-EMF, título 2.3.4.2. * \param ArrayEmrHeader Array con el contenido del registro EMR_HEADER. * \param PrintJob Estructura pasada por referencia para guardar las propiedades del trabajo de impresión * \param Position Posición del registro EMR_HEADER en el fichero de Spool */ private void AnalizeEmrHeader(byte [] ArrayEmrHeader, ref STRUCT_PRINT_JOB PrintJob, int Position) { // Primeros elementos del registro: // - Type: 4 bytes (ya leido) // - Size: 4 bytes (ya leido) // - Bounds: 16 bytes. // - Frame: 16 bytes. PuntoOrigen (Ox, Oy) Punto Final (Fx, Fy) // El resto de elementos no nos analizamos por que no lo necesitamos. int PosicionFrame = 24; // (Type + Size + Bounds) bytes // Coordenadas del frame uint Ox, Oy, Fx, Fy; Ox = (uint)BitConverter.ToInt32(ArrayEmrHeader, PosicionFrame); PosicionFrame += 4; Oy = (uint)BitConverter.ToInt32(ArrayEmrHeader, PosicionFrame); PosicionFrame += 4; Fx = (uint)BitConverter.ToInt32(ArrayEmrHeader, PosicionFrame); PosicionFrame += 4; Fy = (uint)BitConverter.ToInt32(ArrayEmrHeader, PosicionFrame); Log.Info(" " + Util.MostrarHex((UInt32)(Position + PosicionFrame)) + " Frame: " + "(" + Ox.ToString() + ", " + Oy.ToString() + "), (" + Fx.ToString() + ", " + Fy.ToString() + ")"); // El siguiente If es por si un trabajo de impresión no tuviese el mismo tamaño de página para todas las páginas. // Comparamos con el tamaño de página guardado en el trabajo de impresión. Si el tamaño de página del EMR_HEADER es mayor actualizamos en el trabajo de impresion. if ((PrintJob.N_WIDTH * PrintJob.N_LENGTH) < ((Fx - Ox) * (Fy - Oy))) { PrintJob.N_WIDTH = (int)(Fy - Oy); PrintJob.N_LENGTH = (int)(Fx - Ox); } } // Fin LeerEmrHeader
public void EmfSpool_AnalizeEmf_AnalizaFicherosSpoolEMF() { // Struct para almacenar detalles de impresión (el contenido para el test es indiferente STRUCT_PRINT_JOB PrintJob = new STRUCT_PRINT_JOB(); EmfSpool MiEmfSpool; // Path con los ficheros de Spool //string Path = @"D:\SpoolImpresora\Test\EMF"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF"; //string Path = @"D:\SpoolImpresora\Test"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2015-07-23"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-03-30"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-04-01"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-04-07"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-04-27_2016-04-29"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-05-05"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-04-18_2016-04-29"; //string Path = @"D:\TestMonitorImpresion\EMF"; string Path = @"D:\TestMonitorImpresion\PlotterEMF"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-04-12"; //string Path = @"D:\SpoolImpresora\Test\PlotterEMF\2016-04-15"; //string Path = @"D:\SpoolImpresora"; // Directorio donde se encuentran los ficheros de Spool DirectoryInfo Directorio = new DirectoryInfo(Path); foreach (var Archivo in Directorio.GetFiles("*.SPL")) { /// Inicialización (Arrange) /// - Inicializamos la clase para analizar un fichero de Spool MiEmfSpool = new EmfSpool(Path + @"\" + Archivo); /// Ejecución (Act) /// - Ejecutamos el método PrintJob = new STRUCT_PRINT_JOB(); MiEmfSpool.Analize(ref PrintJob); AnalizeJobId.LogPrintJob(ref PrintJob); /// Comprobación (Assert) /// - Se comprueba que el fichero de Spool tiene contenido (no está vacio) /// - Comprobamos que se ha analizado sin errores el fichero de Spool completo Assert.IsTrue(MiEmfSpool.AnalisisCompletado && (MiEmfSpool.SizeFile > 0)); } }
public void JPLSpool_AnalizePJLPClXl_AnalizaContenidoSpoolPJLPClXl() { // Struct para almacenar detalles de impresión (el contenido para el test es indiferente STRUCT_PRINT_JOB PrintJob; // = new STRUCT_PRINT_JOB(); JPLSpool MiJPLSpool; //string Path = @"D:\SpoolImpresora\Test\JPL-PCLXL"; string Path = @"D:\TestMonitorImpresion\JPL-PCLXL"; //string Path = @"D:\TestMonitorImpresion"; //string Path = @"D:\SpoolImpresora\Test\PlotterJPLPCLXL"; // ************** Test con 231 trabajos de impresión pasado correctamente. 8 minutos y 54 segundos ****************** //string Path = @"D:\SpoolImpresora\Test\JPL-PCLXL\HP5500"; // ***************************************************************************************** //string Path = @"D:\SpoolImpresora\Test\JPL-PCLXL\HP5500\01_LOTE"; //string Path = @"D:\SpoolImpresora\Test"; // Directorio donde se encuentran los ficheros de Spool DirectoryInfo Directorio = new DirectoryInfo(Path); foreach (var Archivo in Directorio.GetFiles("*.SPL")) { //Console.WriteLine(archivo.Name); /// Inicialización (Arrange) MiJPLSpool = new JPLSpool(Path + @"\" + Archivo); /// Ejecución (Act) PrintJob = new STRUCT_PRINT_JOB(); MiJPLSpool.Analize(ref PrintJob); AnalizeJobId.LogPrintJob(ref PrintJob); /// Comprobación (Assert) if (MiJPLSpool.ContenidoPCLXL) { Assert.IsTrue(MiJPLSpool.AnalisisCompletado && MiJPLSpool.AnalisisPCLXLCompletado && (MiJPLSpool.SizeFile > 0)); } else { Assert.IsTrue(MiJPLSpool.AnalisisCompletado && (MiJPLSpool.SizeFile > 0)); } } }
/** \brief Log via Email del trabajo de impresión */ private void LogPrintJobMail(ref STRUCT_PRINT_JOB PrintJob) { string TextoMensaje; /// Generamos log con las propiedades del trabajo de impresión TextoMensaje = ((char)13).ToString(); TextoMensaje += (char)9 + "- ID_JOBNAME: " + PrintJob.ID_JOBNAME + (char)13; TextoMensaje += (char)9 + "- ID_FUENTE: " + PrintJob.ID_FUENTE + (char)13; TextoMensaje += (char)9 + "- N_JOB: " + PrintJob.N_JOB + (char)13; TextoMensaje += (char)9 + "- F_PRINTJOB: " + PrintJob.F_PRINTJOB + (char)13; TextoMensaje += (char)9 + "- ID_LOGIN: "******"- ID_PRINTSERVER: " + PrintJob.ID_PRINTSERVER + (char)13; TextoMensaje += (char)9 + "- ID_PRINTER: " + PrintJob.ID_PRINTER + (char)13; TextoMensaje += (char)9 + "- ID_DOCUMENT: " + PrintJob.ID_DOCUMENT + (char)13; TextoMensaje += (char)9 + "- N_PAGES: " + PrintJob.N_PAGES + (char)13; TextoMensaje += (char)9 + "- N_PAGES_PRINTED: " + PrintJob.N_PAGES_PRINTED + (char)13; TextoMensaje += (char)9 + "- N_COLORPAGES: " + PrintJob.N_COLORPAGES + (char)13; TextoMensaje += (char)9 + "- N_LENGTH: " + PrintJob.N_LENGTH + (char)13; TextoMensaje += (char)9 + "- N_WIDTH: " + PrintJob.N_WIDTH + (char)13; TextoMensaje += (char)9 + "- ID_MEDIASIZE: " + PrintJob.ID_MEDIASIZE + (char)13; TextoMensaje += (char)9 + "- N_MEDIASIZE: " + PrintJob.N_MEDIASIZE + (char)13; TextoMensaje += (char)9 + "- ID_ORIENTATION: " + PrintJob.ID_ORIENTATION + (char)13; TextoMensaje += (char)9 + "- N_ORIENTATION: " + PrintJob.N_ORIENTATION + (char)13; TextoMensaje += (char)9 + "- N_COPIES: " + PrintJob.N_COPIES + (char)13; TextoMensaje += (char)9 + "- ID_COLOR: " + PrintJob.ID_COLOR + (char)13; TextoMensaje += (char)9 + "- N_COLOR: " + PrintJob.N_COLOR + (char)13; TextoMensaje += (char)9 + "- ID_DUPLEX: " + PrintJob.ID_DUPLEX + (char)13; TextoMensaje += (char)9 + "- N_DUPLEX: " + PrintJob.N_DUPLEX + (char)13; TextoMensaje += (char)9 + "- ID_STATUS: " + PrintJob.ID_STATUS + (char)13; TextoMensaje += (char)9 + "- ID_ISPLOTTER: " + PrintJob.ID_ISPLOTTER + (char)13; TextoMensaje += (char)9 + "- ID_MEDIATYPE: " + PrintJob.ID_MEDIATYPE + (char)13; TextoMensaje += (char)9 + "- N_MEDIATYPE: " + PrintJob.N_MEDIATYPE + (char)13; TextoMensaje += (char)9 + "- N_JOBSIZE: " + PrintJob.N_JOBSIZE; // Se envía un email con información del Trabajo de impresión en curso Log.Warn(TextoMensaje); }
/** \brief Análisis del trabajo de Impresión. * \return No devuelve nada. * \details * Se guardan en B.D las propiedades del trabajo de impresión obtenidas a través de las API de impresión, del namespace * System.Printing y del análisis de los ficheros de Spool correspondientes al trabajo de impresión. */ private void AnalizePrintJob() // string Printer, string JobId) { // Objeto para permitir una espera en caso de que el fichero de spool este abierto ElapsedTime TiempoEspera; // Fichero de spool que se tiene que analizar FileInfo MiFileInfo; // Estructura utilizada para guardar los trabajos de impresión STRUCT_PRINT_JOB PrintJob = new STRUCT_PRINT_JOB(); this.ID_JOBNAME = ""; this.N_JOB = Convert.ToInt32(this.JobId); this.ID_PRINTER = this.Printer; // La impresora ¿es un plotter? if (Util.ContieneTexto(this.Printer, "Plotter")) { PrintJob.ID_ISPLOTTER = "S"; } else { PrintJob.ID_ISPLOTTER = "N"; } bool AnalizedSpool = false; //Se recuperan los primeros detalles del trabajo de impresión PrintJob.N_JOB = this.N_JOB; PrintJob.ID_PRINTER = this.ID_PRINTER; /// - Propiedades obtenidas a través del namespace System.Printing try { // Recuperamos las propiedades LocalPrinting.DetailsPrint(PrintJob.ID_PRINTER, this.JobId, ref PrintJob); this.ID_JOBNAME = PrintJob.ID_JOBNAME; this.F_PRINTJOB = PrintJob.F_PRINTJOB; Log.Info(" -- Se extraen las propiedades utilizando System.Printing --"); // Generamos log LogPrintJob(ref PrintJob); // Guardamos en B.D SavePrintJob(ref PrintJob); } catch (Exception e) { Log.Fatal("Error extrayendo propiedades a través de System.Printing"); Log.Fatal(e); } /// - Propiedades obtenidas a través de las APIs de impresión LimpiaStrucPrintJob(ref PrintJob); PrintJob.ID_JOBNAME = ID_JOBNAME; try { // Recuperamos las propiedades ApiImpresion MiApiImpresion = new ApiImpresion(); MiApiImpresion.Analize(this.Printer, (uint)Convert.ToInt32(this.JobId), ref PrintJob); // Guardamos en B.D las propiedades obtenidas Log.Info(" -- Se extraen las propiedades utilizando las API de impresión. --"); LogPrintJob(ref PrintJob); SavePrintJob(ref PrintJob); /// Enviamos información del trabajo de impresión via email LogPrintJobMail(ref PrintJob); } catch (Exception e) { Log.Fatal("No se puede analizar el trabajo de impresión: " + this.JobId + " a través de las APIs de winspool.drv."); Log.Fatal(e); } //try /// Para el analisis de ficheros de Spool, antes de empezar, nos aseguramos de que el fichero no está bloqueado // Establecemos un tiempo de espera TiempoEspera = new ElapsedTime(); // Fichero de spool que se tiene que analizar MiFileInfo = new FileInfo(LocalPrinting.PathPrintSpool() + @"\" + this.JobId.PadLeft(5, '0') + ".SPL"); while ((!TiempoEspera.OverElapsedTime()) & WatchIO.IsFileLocked(MiFileInfo)) { // Se da tiempo a que se libere el archivo de Spool System.Threading.Thread.Sleep(10); } /// - Propiedades obtenidas a través del análisis del fichero de Spool con lenguaje EMF LimpiaStrucPrintJob(ref PrintJob); PrintJob.ID_JOBNAME = ID_JOBNAME; if (PrintJob.N_JOBSIZE > 0) { try { Log.Debug("Analizamos si es lenguaje EMF"); // Se comenta la siguiente línea al desactivar la suscripción a los eventos del sistema de archivos de la clase WatchIO EmfSpool MyEmfSpool = new EmfSpool(LocalPrinting.PathPrintSpool() + @"\" + this.JobId.PadLeft(5, '0') + ".SPL"); MyEmfSpool.Analize(ref PrintJob); AnalizedSpool = true; Log.Info("Establecemos como fuente del análisis: EMF"); PrintJob.ID_FUENTE = "EMF"; Log.Info(" -- Se extraen las propiedades utilizando analisis EMF. --"); LogPrintJob(ref PrintJob); SavePrintJob(ref PrintJob); /// Enviamos información del trabajo de impresión via email LogPrintJobMail(ref PrintJob); } catch (Exception e) { Log.Info("El trabajo de impresión: " + this.JobId + " no utiliza lenguaje EMF."); Log.Fatal(e); }//try } /// - Propiedades obtenidas a través del análisis del fichero de Spool con lenguaje JPL. LimpiaStrucPrintJob(ref PrintJob); PrintJob.ID_JOBNAME = ID_JOBNAME; if ((!AnalizedSpool) && (PrintJob.N_JOBSIZE > 0)) { try { Log.Debug("Analizamos si es lenguaje JPL"); // Se comentan las siguientes 2 líneas al desactivar la suscripción a los eventos del sistema de archivos de la clase WatchIO Log.Debug(LocalPrinting.PathPrintSpool() + @"\" + @"\" + this.JobId.PadLeft(5, '0') + ".SPL"); JPLSpool MyJPLSpool = new JPLSpool(LocalPrinting.PathPrintSpool() + @"\" + this.JobId.PadLeft(5, '0') + ".SPL"); MyJPLSpool.Analize(ref PrintJob); AnalizedSpool = true; Log.Info(" -- Se extraen las propiedades utilizando analisis JPL. --"); LogPrintJob(ref PrintJob); SavePrintJob(ref PrintJob); /// Enviamos información del trabajo de impresión via email LogPrintJobMail(ref PrintJob); } catch (Exception e) { Log.Info("No se puede analizar el trabajo de impresión: " + this.JobId + " mediante análisis JPL."); Log.Fatal(e); } //try } //if Log.Debug("Trabajo de impresión: " + this.JobId + "en impresora " + this.Printer + " analizado con éxito"); } //AnalizeSpool()
} // Fin LeerEmrHeader /** \brief Analisis EMF * \details analiza fichero de spool formato EMF para extraer los detalles relevantes de impresión. * Como detalles de impresión importantes en este análisis se extraen el número total de páginas impresas y de * ellas cuantas son en color. * También analizamos los registros DEVMODE. * \param PrintJob Estructura pasada por referencia para guardar las propiedades del trabajo de impresión */ public new void Analize(ref STRUCT_PRINT_JOB PrintJob) { int PosicionEmf = 0; int TipoRegistroEmf; int SizeRegistroEmf; ENUM_EMF.EMRI_RECORD TipoEmfRecord; BinaryReader EmfFile; // ResumenEMR: Objeto de la clase Tags para guardar un resumes de los Tags utilizados Tags ResumenEMF = new Tags(); /// Apertura fichero de Spool try { EmfFile = new BinaryReader(File.Open(this.PathSpoolFile, FileMode.Open)); } catch (Exception e) { Log.Error("No se puede abrir el fichero de spool: " + this.PathSpoolFile); throw e; } /// Análisis fichero de Spool try { Log.Info("Analisis mediante lenguaje EMF del ficheros de Spool: " + this.PathSpoolFile); /// Mientras existan registros EMFSPOOL while (PosicionEmf < this.SizeFile) { /// Nos posicionamos para leer el siguiente registro EMFSPOOL EmfFile.BaseStream.Seek(PosicionEmf, SeekOrigin.Begin); /// Obtenemos el tipo y tamaño de rsgistro EMFSPOOL TipoRegistroEmf = EmfFile.ReadInt32(); SizeRegistroEmf = EmfFile.ReadInt32(); // Determinar el tipo de registro en el enum EmfRecord TipoEmfRecord = (ENUM_EMF.EMRI_RECORD)TipoRegistroEmf; Log.Debug("Posición: (" + Util.MostrarHex((UInt32)PosicionEmf) + ") registro EMF: " + DICTIONARY_EMF.EMRI_RECORD[TipoRegistroEmf] + " Tamaño: " + Util.MostrarHex((UInt32)(SizeRegistroEmf)) + ". "); // Guardamos información del Tag Para presentar resumen al final del análisis ResumenEMF.Agregar(DICTIONARY_EMF.EMRI_RECORD[TipoRegistroEmf]); /// Análisis del registro EMFSPOOL // Según el tipo de registro EMF calculamos la siguiente posicion switch (TipoEmfRecord) { case ENUM_EMF.EMRI_RECORD.HEADER_RECORD: // Analisis Registro Cabecera PosicionEmf = SizeRegistroEmf; break; case ENUM_EMF.EMRI_RECORD.EMRI_DEVMODE: // OK /// Si es registro EMRI_DEVMODE guardamos en el Log su contenido y guardamos propiedades del trabajo de impresión en la estructura con las propiedades del trabajo /// de impresión. int PosicionEmfDevmode = PosicionEmf + 8; // El siguiente método lee el registro DEVMODE y genera el log. Falta implementar el analisis LeerDevmode(ref EmfFile, PosicionEmfDevmode, ref PrintJob); PosicionEmf = PosicionEmf + 8 + SizeRegistroEmf; break; // Los 5 siguientes casos contienen el contenido de la página a imprimir case ENUM_EMF.EMRI_RECORD.EMRI_METAFILE: case ENUM_EMF.EMRI_RECORD.EMRI_FORM_METAFILE: case ENUM_EMF.EMRI_RECORD.EMRI_BW_METAFILE: case ENUM_EMF.EMRI_RECORD.EMRI_BW_FORM_METAFILE: case ENUM_EMF.EMRI_RECORD.EMRI_METAFILE_DATA: /// Si es un registro EMFSPOOL con contenido de página, realizamos un análisis EMF de su contenido. Para ello se utiliza el método AnalizeEMR(). AnalizeEMR(ref EmfFile, PosicionEmf + 8, SizeRegistroEmf, ref ResumenEMF, ref PrintJob); PosicionEmf = PosicionEmf + 8 + SizeRegistroEmf; break; // Los dos siguiente casos marcan el final del contenido de página /// Si el registro EMFSPOOL es del tipo EMRI_METAFILE_EXT -> El contenido de la Pagina es en color case ENUM_EMF.EMRI_RECORD.EMRI_METAFILE_EXT: // Página con contenido en color PrintJob.N_COLORPAGES++; goto case ENUM_EMF.EMRI_RECORD.EMRI_BW_METAFILE_EXT; // Si el registro EMFSPOOL es del tipo EMRI_BW_METAFILE_EXT -> El contenido de la página sólo es en Blanco y Negro. case ENUM_EMF.EMRI_RECORD.EMRI_BW_METAFILE_EXT: //Página con contenido solo en Blanco-Negro PrintJob.N_PAGES++; PrintJob.N_PAGES_PRINTED++; PosicionEmf = PosicionEmf + 8 + SizeRegistroEmf; break; case ENUM_EMF.EMRI_RECORD.EMRI_PS_JOB_DATA: case ENUM_EMF.EMRI_RECORD.EMRI_ENGINE_FONT: case ENUM_EMF.EMRI_RECORD.EMRI_TYPE1_FONT: case ENUM_EMF.EMRI_RECORD.EMRI_DESIGNVECTOR: case ENUM_EMF.EMRI_RECORD.EMRI_SUBSET_FONT: case ENUM_EMF.EMRI_RECORD.EMRI_DELTA_FONT: case ENUM_EMF.EMRI_RECORD.EMRI_ENGINE_FONT_EXT: case ENUM_EMF.EMRI_RECORD.EMRI_TYPE1_FONT_EXT: case ENUM_EMF.EMRI_RECORD.EMRI_DESIGNVECTOR_EXT: case ENUM_EMF.EMRI_RECORD.EMRI_SUBSET_FONT_EXT: case ENUM_EMF.EMRI_RECORD.EMRI_DELTA_FONT_EXT: case ENUM_EMF.EMRI_RECORD.EMRI_EMBED_FONT_EXT: case ENUM_EMF.EMRI_RECORD.EMRI_PRESTARTPAGE: PosicionEmf = PosicionEmf + 8 + SizeRegistroEmf; break; default: Log.Fatal("No existe el tipo de registro EMF: " + Util.MostrarHex((UInt32)TipoEmfRecord)); throw new Exception("No existe el tipo de registro EMF: " + Util.MostrarHex((UInt32)TipoEmfRecord)); } //switch Log.Debug("Posicion siguiente registro EMFSPOOL: (" + Util.MostrarHex((UInt32)(PosicionEmf)) + ")"); } //while } //try catch (Exception e) { EmfFile.Close(); Log.Info("El fichero de Spool no se ha podido analizar mediante lenguaje EMF"); throw e; } Log.Info("Cerramos el fichero EMF"); /// Se cierra el fichero de Spool EmfFile.Close(); /// Se genera log con el resumen del análisis EMF del fichero de Spool ResumenEMF.ResumenTags(); Log.Info("FIN Analisis EMF"); Log.Info("----------------------------------------------"); AnalisisCompletado = true; } //AnalizeEmf()
/** \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()
//public static void AnalizePrintJob(string IImpresora, uint IJobId) //(PRINTER_ENUM Flags) /** \brief Extrae las propiedades de un Trabajo de Impresión. * \details A través de las APIs proporcionadas a través de la librería winspool.drv * \param Printer string con el nombre de la Impresora * \param IJobId Número del trabajo de impresión * \param PrintJob struct tipo STRUCT_PRINT_JOB en el que se devuelven las propiedades del trabajo de impresión * \return No devuelve nada */ public void Analize(string Printer, uint JobId, ref STRUCT_PRINT_JOB PrintJob) //(PRINTER_ENUM Flags) //public static void Analize(string Printer, uint IJobId, ref STRUCT_PRINT_JOB PrintJob) //(PRINTER_ENUM Flags) { STRUCT_API_PRINTING.JOB_INFO_2 JobInfo2; ///> Estructura en la que GetJob2() devuelve las propiedades de impresión STRUCT_API_PRINTING.DEVMODE DevMode; ///> Estructura contenido en JOB_INFO_2 IntPtr WphPrinter; IntPtr WpPrinterEnum = IntPtr.Zero; IntPtr WpJob = IntPtr.Zero; STRUCT_API_PRINTING.PRINTER_DEFAULTS WpPrinterDefaults = new STRUCT_API_PRINTING.PRINTER_DEFAULTS(); Log.Info("========================================================================="); Log.Info(" API WINSPOOL.drv"); Log.Info("========================================================================="); Log.Info(""); /// Se abre la conexión con la impresora if (OpenPrinter(Printer, out WphPrinter, ref WpPrinterDefaults)) { Log.Info("Este es el contenido de WphPrinter: #" + WphPrinter.ToString() + "."); } else { Log.Info("No se ha podido encontrar la impresora: -" + Printer); } /// Recupera estructura tipo JOB_INFO_2 con las propiedades del trabajo de impresión JobInfo2 = GetJob2(WphPrinter, JobId); DevMode = (STRUCT_API_PRINTING.DEVMODE)Marshal.PtrToStructure(JobInfo2.pDevMode, typeof(STRUCT_API_PRINTING.DEVMODE)); /// Se recuperan los valores del trabajo de impresión en el struct STRUCT_PRINT_JOB //PrintJob.ID_JOBNAME: Se mantiene el valor que tiene. PrintJob.ID_FUENTE = "API"; PrintJob.N_JOB = (int)JobInfo2.JobId; // PrintJob.F_PRINTJOB. Se mantiene la obtenida, debería ser la obtenida antes a través de System.Printing. El campo JobInfo2.Submitted está sin contenido PrintJob.ID_LOGIN = JobInfo2.pUserName; PrintJob.ID_PRINTSERVER = JobInfo2.pMachineName; PrintJob.ID_PRINTER = JobInfo2.pPrinterName; PrintJob.ID_DOCUMENT = JobInfo2.pDocument; PrintJob.N_PAGES = (int)JobInfo2.Size; PrintJob.N_PAGES_PRINTED = PrintJob.N_PAGES; // Se mantiene el valor que tiene PrintJob.N_COLORPAGES = PrintJob.N_PAGES; //Se mantiene el valor que tiene PrintJob.N_LENGTH = DevMode.PaperLength; PrintJob.N_WIDTH = DevMode.PaperWidth; try { PrintJob.ID_MEDIASIZE = DICTIONARY_API_PRINTING.PAPERSIZE[DevMode.PaperSize]; } catch (Exception e) { Log.Error("No se encuentra en el diccionario DICTIONARY_API_PRINTING.PAPERSIZE el valor: " + DevMode.PaperSize.ToString()); PrintJob.ID_MEDIASIZE = ""; } PrintJob.N_MEDIASIZE = DevMode.PaperSize; //Orientación papel try { PrintJob.ID_ORIENTATION = DICTIONARY_API_PRINTING.ORIENTATION[DevMode.Orientation]; } catch (Exception e) { Log.Error("No se encuentra en el diccionario DICTIONARY_API_PRINTING.ORIENTATION el valor: " + DevMode.Orientation.ToString()); PrintJob.ID_ORIENTATION = ""; } PrintJob.N_ORIENTATION = DevMode.Orientation; PrintJob.N_COPIES = DevMode.Copies; // Color try { PrintJob.ID_COLOR = DICTIONARY_API_PRINTING.COLORSPACE[DevMode.Color]; } catch (Exception e) { Log.Error("No se encuentra en el diccionario DICTIONARY_API_PRINTING.COLORSPACE el valor: " + DevMode.Color.ToString()); PrintJob.ID_COLOR = ""; } PrintJob.N_COLOR = DevMode.Color; // duplex try { PrintJob.ID_DUPLEX = DICTIONARY_API_PRINTING.DUPLEX_PAGEMODE[DevMode.Duplex]; } catch (Exception e) { Log.Error("No se encuentra en el diccionario DICTIONARY_API_PRINTING.DUPLEX_PAGEMODE el valor: " + DevMode.Duplex.ToString()); PrintJob.ID_DUPLEX = ""; } PrintJob.N_DUPLEX = DevMode.Duplex; PrintJob.ID_STATUS = JobInfo2.Status.ToString(); PrintJob.N_MEDIATYPE = (int)DevMode.MediaType; /// Se cierra la conexión con la impresora try { ClosePrinter(WphPrinter); } catch (Exception ex) { Log.Error("No se ha podido Cerrar la impresora: -" + Printer + (char)13 + ex); } } //AnalizePrintJob()
} // Fin Spool() /** \brief Con este método se realiza el análisis del fichero de Spool. * \details Su implementación se desarrolla en las clases hijas. */ protected void Analize(ref STRUCT_PRINT_JOB PrintJob) { }
} // Fin PCLXLSpool() /** \brief Analisis contenido PCLXL del fichero de Spool de impresión. * \param PrintJob struct con las propiedades del trabajo de impresión */ public new void Analize(ref STRUCT_PRINT_JOB PrintJob) { string HeaderPCLXL = ""; //byte PCLXLByte = 0; byte PCLXLByte; // Variable principal con la que se va analizando el contenido PCLXL. byte PCLXL_Byte_Attribute = 0; // Se guarda el valor del atributo. string PCLXL_Value = ""; // Atributo con valor simple. byte [] PCLXLValueArray = null; // Array donde se guarda el valor del Atributo(byte a byte). int PosicionPCLXL = this.BeginBlockPCLXL; int PosicionCabeceraPCLXL = 0; int NBytes = 0; // Variable utilizada para indicar un número de bytes byte[] ArrayPCLXSizeArray; // Utilizada para leer bloques de bytes int ArrayPCLXLValue = 0; // Utilizar para indicar el tamaño en bytes // Estructura para guardar las propiedades de color de la página PCLXL que se está analizando. // Inicialización por defecto sin elementos en color STRUCT_PCLXL.PCLXLPageState PCLXLPageState = new STRUCT_PCLXL.PCLXLPageState("eGray", false); // Registro para guardar posiciones del Tag PCLXL a analizar PositionTagPCLXL PosTagPCLXL; PosTagPCLXL.AnalizeTag = 0; PosTagPCLXL.Value = 0; PosTagPCLXL.Attribute = 0; // Colas para guardar información de los atributos asociados a un operador(primero en entrar primero en salir). // Utilizado para análisis PCLXL para cada grupo (operador + 1 a N (atributo+valor)) Queue ColaAtributos = new Queue(); // Variable auxiliar para almacenar el Valor del atributo string sValue = ""; int iValue = 0; // Variable para obtener resumen Analisis Tags ResumenPCLXL = new Tags(); Log.Info("/*------------------------------------------------------------------------------------------*/"); Log.Info(" INICIO ANALISIS PCLXL "); Log.Info("/*------------------------------------------------------------------------------------------*/" + (char)Util._END_LINE1); Log.Info("Fichero de Spool a analizar contenido PCLXL: " + this.PathSpoolFile); Log.Info("Desde la posición: " + Util.MostrarHex((UInt32)(this.BeginBlockPCLXL)) + ", hasta la posición: " + Util.MostrarHex((UInt32)(this.EndBlockPCLXL))); /// Lectura de la cabecera del bloque PCLXL<br> // Ignoramos los primeros bytes hasta obtener el identificador de formato de representación(Binding Format): {"'" | ")" | "("}. Comienzo cabecera PCLXL ") HP-PCL XL ......." do { PCLXLByte = this.ArrayPCLXLSpool[PosicionPCLXL]; PosicionPCLXL++; } while ((PCLXLByte != Util._BINDING_FORMAT_COMILLA) && (PCLXLByte != Util._BINDING_FORMAT_PARENTESIS_DERECHO) && (PCLXLByte != Util._BINDING_FORMAT_PARENTESIS_IZQUIERDO)); // Encontrado el identificador nos volvemos a posicionar y guardamos la posición de la cabecera PosicionPCLXL--; PosicionCabeceraPCLXL = PosicionPCLXL; // Leemos la cabecera PCLXL do { PCLXLByte = this.ArrayPCLXLSpool[PosicionPCLXL]; PosicionPCLXL++; HeaderPCLXL = HeaderPCLXL + (char)PCLXLByte; } while ((PCLXLByte != Util._END_LINE1) && (PCLXLByte != Util._END_LINE2)); Log.Info("Posición: (" + Util.MostrarHex((UInt32)PosicionCabeceraPCLXL) + "): " + "CABECERA: '" + HeaderPCLXL + "'"); // Leida la cabecera guardamos la posición en la que empezamos a analizar Log.Info("Posición: (" + Util.MostrarHex((UInt32)(PosicionPCLXL)) + "): " + " - Comienza analisis Bloque datos PCLXL."); try { /// Bucle para analizar los TAGS PCLXL del Spool<br> while (PosicionPCLXL <= this.EndBlockPCLXL) { /// Nos posicionamos en el siguiente TAG PCLXL a Analizar PosTagPCLXL.AnalizeTag = PosicionPCLXL; PosTagPCLXL.Value = 0; PosTagPCLXL.Attribute = 0; /// Leemos TAG PCLXL y nos movemos a la siguiente posición PCLXLByte = this.ArrayPCLXLSpool[PosicionPCLXL]; PosicionPCLXL++; /// Analizamos el TAG PCLXL switch (DICTIONARY_PCLXL.TYPE_TO_TAG[DICTIONARY_PCLXL.TAG_TO_TYPE[PCLXLByte]]) { /// - Análisis para TAG Tipo de Dato case ENUM_PCLXL.TAGTYPE.DataType: /// Es un Tipo de Dato Simple if (DICTIONARY_PCLXL.DATA_TYPE_SIMPLE_LEN.ContainsKey(((ENUM_PCLXL.DATATYPE)PCLXLByte).ToString("F"))) { // Guardamos la posición del Valor del atributo PosTagPCLXL.Value = PosicionPCLXL; // Número de bytes que ocupa el dato simple. NBytes = DICTIONARY_PCLXL.DATA_TYPE_SIMPLE_LEN[Enum.GetName(typeof(ENUM_PCLXL.DATATYPE), PCLXLByte)]; // Obtnemos el Valor //byte[] SimplePCLXLSizeSimple = new byte[NBytes]; PCLXLValueArray = new byte[NBytes]; //Array.Copy(this.ArrayPCLXLSpool, PosicionPCLXL, SimplePCLXLSizeSimple, 0, NBytes); Array.Copy(this.ArrayPCLXLSpool, PosicionPCLXL, PCLXLValueArray, 0, NBytes); //PCLXL_Value = Util.MostrarHex(SimplePCLXLSizeSimple); PCLXL_Value = Util.MostrarHex(PCLXLValueArray); // Obtenemos y guardamos la posicion del Atributo PosicionPCLXL = PosicionPCLXL + NBytes; PosTagPCLXL.Attribute = PosicionPCLXL; } // End if Datos Simples /// Es un Tipo de Dato Array if (DICTIONARY_PCLXL.DATA_TYPE_ARRAY_LEN.ContainsKey(((ENUM_PCLXL.DATATYPE)PCLXLByte).ToString("F"))) { /** \remarks * El tipo de dato para array está compuesto por 3 elementos, de la siguiente forma:<br> * <code>(A B C)<br> * | | '-> (tamaño en bytes obtenido de B). El valor de este elemento indica el tamaño del array<br> * | '-> (1 byte). Con su valor se obtiene el tipo (ENUM_PCLXL.DATATYPE) de dato de C (número de bytes del elemento C)<br> * '-> (1 byte). Indica que es un array y el tipo de dato de cada elemento del array(PCLXLByte. En ENUM_PCLXL.DATATYPE)<br> * </code> * * Ejem-1: 0xc8c002 (Se trata de un array de 2 elementos de tipo ubyte.) * A: c8(1 byte): indica que es un array de tipos de datos ubyte (ENUM_PCLXL.DATATYPE). * B: c0(1 byte): Indica el tipo de datos, tamaño, necesario para almacenar la longitud del array ubyte (1 byte) del siguiente campo(02). * C: 02(1 byte): Valor 2. * Ejem-2: 0xc8c11000 (Se trata de un array de 16 elementos de tipo ubyte.) * A: c8: indica que es un array de tipos de datos ubyte (ENUM_PCLXL.DATATYPE). * B: c1: Tipo de dato numérico uint16 (2 bytes). * C: 1000: Valor 16 en decimal (Hexadecimal Little Endian: Bytes menos significativos primero). */ // Contenido elemento B (this.ArrayPCLXLSpool[PosicionPCLXL]). nos da el tamaño en byte del siguiente elemento: C NBytes = DICTIONARY_PCLXL.DATA_TYPE_SIMPLE_LEN[Enum.GetName(typeof(ENUM_PCLXL.DATATYPE), (byte)this.ArrayPCLXLSpool[PosicionPCLXL])]; // Nos movemos a la posicion del elemento C PosicionPCLXL++; // Leemos el siguiente campo en un array. Contiene el número de elementos del array // --------------------------------------------------------------------------------- ArrayPCLXLValue = 0; // Número de elementos del array que contiene el valor ArrayPCLXSizeArray = new byte[NBytes]; // Tamaño: número de bytes del tipo de dato Array.Copy(this.ArrayPCLXLSpool, PosicionPCLXL, ArrayPCLXSizeArray, 0, NBytes); // Leemos el tamaño o número de elementos del array: ArrayPCLXLValue switch (NBytes) { case 1: // 1 byte ArrayPCLXLValue = (int)ArrayPCLXSizeArray[0]; break; case 2: // 2 bytes ArrayPCLXLValue = (int)BitConverter.ToInt16(ArrayPCLXSizeArray, 0); break; case 4: // 4 bytes ArrayPCLXLValue = (int)BitConverter.ToInt32(ArrayPCLXSizeArray, 0); break; } /// - Obtenemos el Valor // Guardamos la posición del valor del atributo PosicionPCLXL = PosicionPCLXL + NBytes; PosTagPCLXL.Value = PosicionPCLXL; // Calculamos el número total de bytes que ocupa el array NBytes = DICTIONARY_PCLXL.DATA_TYPE_ARRAY_LEN[Enum.GetName(typeof(ENUM_PCLXL.DATATYPE), PCLXLByte)] * ArrayPCLXLValue; /// - Guardamos el valor del atributo en array de datos PCLXLValueArray = new byte[NBytes]; Array.Copy(this.ArrayPCLXLSpool, PosTagPCLXL.Value, PCLXLValueArray, 0, NBytes); // Para mostrar en el Log el tamaño del array PCLXL_Value = NBytes.ToString() + " bytes"; // Posición del Attributo PosicionPCLXL += NBytes; PosTagPCLXL.Attribute = PosicionPCLXL; } // if para Arrays /// - Obtenemos el atributo // leemos el AttributeDefiner para ver la longitud del atributo switch (this.ArrayPCLXLSpool[PosicionPCLXL]) { case (byte)ENUM_PCLXL.ATTRIBUTE_DEFINER.ubyte: PosicionPCLXL++; PCLXL_Byte_Attribute = this.ArrayPCLXLSpool[PosicionPCLXL]; PosicionPCLXL++; break; // El siguiente caso para atributos de 2 bytes no se utiliza // case (byte)PCLXL_ENUM.PCLXL_ATTRIBUTE_DEFINER.uint16: // PCLXL_int16_Attribute = PCLXLFile.ReadUInt16(); // PosicionPCLXL = PosicionPCLXL + 3; // break; default: Log.Error("Posición: (" + Util.MostrarHex((UInt32)(PosicionPCLXL)) + ")>>> " + "No se ha encontrado el TagAttribute Definer"); PosicionPCLXL++; break; } /// Disponemos de: /// - Atributo : PCLXL_Byte_Attribute /// - Valor : PCLXL_Value /// - Tipo de Dato: PCLXLByte /// Guardamos esta información en una Cola para almacenar posteriormenete en el Log del Monitor de Impresión /// - Guardamos el tipo de dato ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.AnalizeTag)) + " " + "PCLXL Data Type " + Util.MostrarHex(PCLXLByte) + " " + DICTIONARY_PCLXL.DATATYPE[PCLXLByte]); /// - Guardamos el Valor. //Para atributos relacionados con el color de impresión, mostramos su valor con el mayor detalle switch ((ENUM_PCLXL.ATTRIBUTE)PCLXL_Byte_Attribute) { case ENUM_PCLXL.ATTRIBUTE.ColorSpace: sValue = DICTIONARY_PCLXL.COLORSPACE[PCLXLValueArray[0]]; ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Value)) + " " + " Value " + sValue); // Actualizamos la propiedad SpaceColor en la página actual PCLXLPageState.SetColorSpace(sValue); break; case ENUM_PCLXL.ATTRIBUTE.RGBColor: sValue = "(" + PCLXLValueArray[0].ToString() + ", " + PCLXLValueArray[1].ToString() + ", " + PCLXLValueArray[2].ToString() + ")"; ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Value)) + " " + " Value " + sValue); // Actualizamos la propiedad Color en la página Actual si todavía no contiene ninguna impresión en Color if (!PCLXLPageState.IsColorPage()) { PCLXLPageState.SetColorPage(sValue); } break; case ENUM_PCLXL.ATTRIBUTE.ColorMapping: ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Value)) + " " + " Value " + DICTIONARY_PCLXL.COLORMAPPING[PCLXLValueArray[0]]); break; case ENUM_PCLXL.ATTRIBUTE.ColorDepth: ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Value)) + " " + " Value " + DICTIONARY_PCLXL.COLORDEPTH[PCLXLValueArray[0]]); break; default: ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Value)) + " " + " Value " + PCLXL_Value); break; } /// - Guardamos el Atributo ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Attribute)) + " " + " PCLXL Attribute " + Util.MostrarHex(PCLXL_Byte_Attribute) + " " + DICTIONARY_PCLXL.ATTRIBUTE[PCLXL_Byte_Attribute]); // Atributo MediaSize if (PCLXL_Byte_Attribute == (int)ENUM_PCLXL.ATTRIBUTE.MediaSize) { Log.Debug("============================================> MediaSize"); } /// Si el atributo es alguno de estos {DUPLEX; ORIENTATION, MEDIASIZE, COLOR} lo actualizamos en el trabajo de impresión switch ((ENUM_PCLXL.ATTRIBUTE)PCLXL_Byte_Attribute) { case ENUM_PCLXL.ATTRIBUTE.DuplexPageMode: // Valor es un byte PrintJob.ID_DUPLEX = DICTIONARY_PCLXL.DUPLEX_PAGEMODE[Util.ConvertStringHexToInt(PCLXL_Value)]; PrintJob.N_DUPLEX = Util.ConvertStringHexToInt(PCLXL_Value); break; case ENUM_PCLXL.ATTRIBUTE.Orientation: // Valor es un byte PrintJob.ID_ORIENTATION = DICTIONARY_PCLXL.ORIENTATION[Util.ConvertStringHexToInt(PCLXL_Value)]; PrintJob.N_ORIENTATION = Util.ConvertStringHexToInt(PCLXL_Value); break; case ENUM_PCLXL.ATTRIBUTE.PageCopies: // Valor es un byte. Propiedad para cada página iValue = Util.ConvertStringHexToInt(PCLXL_Value); Log.Debug("*************************NUMERO DE COPIAS: " + iValue.ToString()); PrintJob.N_COPIES = iValue; Log.Debug("*************************NUMERO DE PAGINAS ANTES DE ACTUALIZAR: " + PrintJob.N_PAGES.ToString()); PrintJob.N_PAGES = PrintJob.N_PAGES + iValue; Log.Debug("*************************NUMERO DE PAGINAS DESPUES DE ACTUALIZAR: " + PrintJob.N_PAGES.ToString()); if (PCLXLPageState.IsColorPage()) { PrintJob.N_COLORPAGES = PrintJob.N_COLORPAGES + iValue; } Log.Debug("*************************NUMERO DE PAGINAS COLOR: " + PrintJob.N_COLORPAGES.ToString()); break; case ENUM_PCLXL.ATTRIBUTE.MediaSize: // Valor es una cadena(array) if (PrintJob.ID_MEDIASIZE == "") { PrintJob.ID_MEDIASIZE = Util.ConverArrayToString(PCLXLValueArray); } //PCLXLValueArray break; case ENUM_PCLXL.ATTRIBUTE.ColorSpace: // Valor es un byte PrintJob.ID_COLOR = DICTIONARY_PCLXL.COLORSPACE[Util.ConvertStringHexToInt(PCLXL_Value)]; PrintJob.N_COLOR = Util.ConvertStringHexToInt(PCLXL_Value); //PaletteDepth, RGBColor, ColorDepthArray, ColorDepth, ColorMapping, ColorTreatment break; default: // Marcamos en el log para supervisar en el log los atributos relacionados con el color y con el tamaño de página if ("PaletteDepthColorSpaceGrayLevelRGBColorColorDepthColorMappingColorTreatmentNewDestinationSizeMediaSizeCustomMediaSizeCustomMediaSizeUnitsDestinationSize".Contains(DICTIONARY_PCLXL.ATTRIBUTE[PCLXL_Byte_Attribute])) { Log.Debug(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Attribute)) + " " + " PCLXL Attribute " + Util.MostrarHex(PCLXL_Byte_Attribute) + " " + DICTIONARY_PCLXL.ATTRIBUTE[PCLXL_Byte_Attribute] + "********************************************************"); } break; } break; case ENUM_PCLXL.TAGTYPE.AttributeDefiner: break; case ENUM_PCLXL.TAGTYPE.Attribute: Log.Fatal("Nunca se debería obtener el atributo directamente. Cuando se detecta un Tipo de dato se obtiene su valor y a que atributo se vincula."); break; /// - Análisis para TAG EmbedDataDefiner case ENUM_PCLXL.TAGTYPE.EmbedDataDefiner: // Total de bytes del siguiente campo donde se guarda tamaño de los Embedded Data NBytes = DICTIONARY_PCLXL.EMBED_DATA_DEFINER_LEN[Enum.GetName(typeof(ENUM_PCLXL.EMBED_DATA_DEFINER), (byte)PCLXLByte)]; ArrayPCLXLValue = 0; ArrayPCLXSizeArray = new byte[NBytes]; // Nos posicionamos para leer los Embedded Data Array.Copy(this.ArrayPCLXLSpool, PosicionPCLXL, ArrayPCLXSizeArray, 0, NBytes); PosicionPCLXL += NBytes; PosTagPCLXL.Value = PosicionPCLXL; // ArrayPCLXLValue se guarda el valor del número de bytes de los embedded Data switch (NBytes) { case 1: // 1 byte ArrayPCLXLValue = (int)ArrayPCLXSizeArray[0]; break; case 4: // 4 bytes ArrayPCLXLValue = (int)BitConverter.ToInt32(ArrayPCLXSizeArray, 0); break; } // Nos posicionamos a continuación de los Embedded Data PosicionPCLXL += ArrayPCLXLValue; // Disponemos de: // - Atributo : PCLXL_Byte_Attribute // - Valor : PCLXL_Value // - Tipo de Dato: PCLXLByte // Guardamos el Analisis de los Tags Encontrados para generar el Log ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.AnalizeTag)) + " " + "PCLXL Data Type " + Util.MostrarHex(PCLXLByte) + " " + Enum.GetName(typeof(ENUM_PCLXL.EMBED_DATA_DEFINER), PCLXLByte)); ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.AnalizeTag + 1)) + " " + " PCLXL Embedded Len. " + Util.MostrarHex((UInt32)(ArrayPCLXLValue))); ColaAtributos.Enqueue(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.Value)) + " " + " Data [" + ArrayPCLXLValue.ToString("D") + " bytes]"); break; case ENUM_PCLXL.TAGTYPE.Whitespace: // No se analiza break; /// Análisis para TAG tipo Operador case ENUM_PCLXL.TAGTYPE.Operator: /// Filtramos los operadores que nos interesan Si es final de página actualizamos propiedades del trabajo de impresión /// Si el operador es alguno de estos {DUPLEX; ORIENTATION, MEDIASIZE, COLOR} actualizamos el trabajo de impresión switch ((ENUM_PCLXL.OPERATOR)PCLXLByte) { case ENUM_PCLXL.OPERATOR.EndPage: ColaAtributos.Enqueue("Número de página: " + PrintJob.N_PAGES.ToString()); goto default; case ENUM_PCLXL.OPERATOR.BeginPage: // Inicio página todavía no se ha imprimido nada en Color PCLXLPageState.ResetColorPage(); goto default; case ENUM_PCLXL.OPERATOR.BeginSession: goto default; case ENUM_PCLXL.OPERATOR.BeginImage: // Si ColorSpace actual es RGB la imagen se imprime en Color if (PCLXLPageState.IsRGBSpace()) { PCLXLPageState.SetColorPage(true); } goto default; case ENUM_PCLXL.OPERATOR.ReadImage: case ENUM_PCLXL.OPERATOR.EndImage: case ENUM_PCLXL.OPERATOR.SetColorTreatment: case ENUM_PCLXL.OPERATOR.SetColorTrapping: case ENUM_PCLXL.OPERATOR.SetBrushSource: case ENUM_PCLXL.OPERATOR.SetPenSource: case ENUM_PCLXL.OPERATOR.PushGS: case ENUM_PCLXL.OPERATOR.PopGS: case ENUM_PCLXL.OPERATOR.SetColorSpace: case ENUM_PCLXL.OPERATOR.EndSession: default: // Primero mostramos información de los atributos del operador while (ColaAtributos.Count > 0) { Log.Debug(ColaAtributos.Dequeue()); } // Información del operador Log.Debug(" Pos. " + Util.MostrarHex((UInt32)(PosTagPCLXL.AnalizeTag)) + " " + "PCLXL " + Enum.GetName(typeof(ENUM_PCLXL.TAGTYPE), ENUM_PCLXL.TAGTYPE.Operator) + " ===>>> " + Util.MostrarHex(PCLXLByte) + " " + DICTIONARY_PCLXL.OPERATOR[PCLXLByte]); Log.Debug("--------------------------------------------------------------------------------"); // Guardar operador para mostrar un Resumen de tags ResumenPCLXL.Agregar(DICTIONARY_PCLXL.OPERATOR[PCLXLByte]); break; } if (ENUM_PCLXL.OPERATOR.EndPage == (ENUM_PCLXL.OPERATOR)PCLXLByte) { /// - Código para actualizar propiedades del trabajo de impresión } break; case ENUM_PCLXL.TAGTYPE.Indefinido: Log.Error("El Tag PCLXL: " + Util.MostrarHex(PCLXLByte) + " no está definido"); break; } } // End While } catch (Exception) { throw new Exception("Falla el análisis PCLXL del fichero: " + this.PathSpoolFile + " con " + this.SizeFile + " bytes."); } Log.Info("Posición: (" + Util.MostrarHex((UInt32)(PosicionPCLXL - 1)) + "): " + " - Finaliza analisis Bloque datos PCLXL."); // Se genera log con un resumen de los Tags para operadores ResumenPCLXL.ResumenTags(); Log.Info("/*------------------------------------------------------------------------------------------*/"); Log.Info(" FIN ANALISIS PCLXL"); Log.Info("/*------------------------------------------------------------------------------------------*/" + (char)Util._END_LINE1); // Control para realizar pruebas automáticas this.AnalisisCompletado = true; } // Fin AnalizePCLXL()
/** \brief Lectura registro DEVMODE * \details Lectura y analisis registro DEVMODE, a partir de la posición en el fichero de Spool. Su estructura se define en el documento MS-RPRN 2.2.2.1 * \param EmfFile referencia a fichero EMF * \param PositionDEVMODE posicion del registro DEVMODE en el fichero EMF * \param PrintJob Estructura pasada por referencia para guardar las propiedades del trabajo de impresión */ //private void LeerDevmode(string PathFile, int posicionDEVMODE) private void LeerDevmode(ref BinaryReader EmfFile, int PositionDEVMODE, ref STRUCT_PRINT_JOB PrintJob) { STRUCT_API_PRINTING.DEVMODE RegDevmode = new STRUCT_API_PRINTING.DEVMODE(); //BinaryReader EmfFile = new BinaryReader(File.Open(PathFile, FileMode.Open)); /// Se obtiene el contenido del registro EMRI_DEVMODE en una estructura tipo DEVMODE EmfFile.BaseStream.Seek(PositionDEVMODE, SeekOrigin.Begin); RegDevmode.DeviceName = Util.DevmodeString32(EmfFile.ReadBytes(64)); RegDevmode.SpecVersion = (ushort)EmfFile.ReadInt16(); RegDevmode.DriverVersion = (ushort)EmfFile.ReadInt16(); RegDevmode.Size = (ushort)EmfFile.ReadInt16(); RegDevmode.DriverExtra = (ushort)EmfFile.ReadInt16(); RegDevmode.Fields = (uint)EmfFile.ReadInt32(); RegDevmode.Orientation = EmfFile.ReadInt16(); RegDevmode.PaperSize = EmfFile.ReadInt16(); RegDevmode.PaperLength = EmfFile.ReadInt16(); RegDevmode.PaperWidth = EmfFile.ReadInt16(); RegDevmode.Scale = EmfFile.ReadInt16(); RegDevmode.Copies = EmfFile.ReadInt16(); RegDevmode.DefaultSource = EmfFile.ReadInt16(); RegDevmode.PrintQuality = EmfFile.ReadInt16(); RegDevmode.Color = EmfFile.ReadInt16(); RegDevmode.Duplex = EmfFile.ReadInt16(); RegDevmode.YResolution = EmfFile.ReadInt16(); RegDevmode.TTOption = EmfFile.ReadInt16(); RegDevmode.Collate = EmfFile.ReadInt16(); RegDevmode.FormName = Util.DevmodeString32(EmfFile.ReadBytes(64)); RegDevmode.LogPixels = (ushort)EmfFile.ReadInt16(); RegDevmode.BitsPerPel = (uint)EmfFile.ReadInt32(); RegDevmode.PelsWidth = (uint)EmfFile.ReadInt32(); RegDevmode.PelsHeight = (uint)EmfFile.ReadInt32(); RegDevmode.Nup = (uint)EmfFile.ReadInt32(); RegDevmode.DisplayFrequency = (uint)EmfFile.ReadInt32(); RegDevmode.ICMMethod = (uint)EmfFile.ReadInt32(); RegDevmode.ICMIntent = (uint)EmfFile.ReadInt32(); RegDevmode.MediaType = (uint)EmfFile.ReadInt32(); RegDevmode.DitherType = (uint)EmfFile.ReadInt32(); RegDevmode.Reserved1 = (uint)EmfFile.ReadInt32(); RegDevmode.Reserved2 = (uint)EmfFile.ReadInt32(); RegDevmode.PanningWidth = (uint)EmfFile.ReadInt32(); RegDevmode.PanningHeight = (uint)EmfFile.ReadInt32(); /// Generación de log con el contenido del registro DEVMODE Log.Info("<<<<<<<<<<<<<<< Registro DEVMODE en fichero de Spool con lenguaje EMF >>>>>>>>>>>>>>>>"); Log.Info(" - DeviceName: " + RegDevmode.DeviceName); Log.Info(" - SpecVersion: " + RegDevmode.SpecVersion); Log.Info(" - DriverVersion: " + RegDevmode.DriverVersion); Log.Info(" - Size: " + RegDevmode.Size); Log.Info(" - DriverExtra: " + RegDevmode.DriverExtra); Log.Info(" - Fields: " + RegDevmode.Fields); Log.Info(" - Orientation: " + RegDevmode.Orientation); Log.Info(" - PaperSize: " + RegDevmode.PaperSize); Log.Info(" - PaperLength: " + RegDevmode.PaperLength); Log.Info(" - PaperWidth: " + RegDevmode.PaperWidth); Log.Info(" - Scale: " + RegDevmode.Scale); Log.Info(" - Copies: " + RegDevmode.Copies); Log.Info(" - DefaultSource: " + RegDevmode.DefaultSource); Log.Info(" - PrintQuality: " + RegDevmode.PrintQuality); Log.Info(" - Color: " + RegDevmode.Color); Log.Info(" - Duplex: " + RegDevmode.Duplex); Log.Info(" - YResolution: " + RegDevmode.YResolution); Log.Info(" - TTOption: " + RegDevmode.TTOption); Log.Info(" - Collate: " + RegDevmode.Collate); Log.Info(" - FormName: " + RegDevmode.FormName); Log.Info(" - LogPixels: " + RegDevmode.LogPixels); Log.Info(" - BitsPerPel: " + RegDevmode.BitsPerPel); Log.Info(" - PelsWidth: " + RegDevmode.PelsWidth); Log.Info(" - PelsHeight: " + RegDevmode.PelsHeight); Log.Info(" - Nup: " + RegDevmode.Nup); Log.Info(" - DisplayFrequency: " + RegDevmode.DisplayFrequency); Log.Info(" - ICMMethod: " + RegDevmode.ICMMethod); Log.Info(" - ICMIntent: " + RegDevmode.ICMIntent); Log.Info(" - MediaType: " + RegDevmode.MediaType); Log.Info(" - DitherType: " + RegDevmode.DitherType); Log.Info(" - Reserved1: " + RegDevmode.Reserved1); Log.Info(" - Reserved2: " + RegDevmode.Reserved2); Log.Info(" - PanningWidth: " + RegDevmode.PanningWidth); Log.Info(" - PanningHeight: " + RegDevmode.PanningHeight); Log.Info(""); /// Propiedades del Trabajo de impresión PrintJob.ID_PRINTER = RegDevmode.DeviceName; PrintJob.N_LENGTH = RegDevmode.PaperLength; PrintJob.N_WIDTH = RegDevmode.PaperWidth; PrintJob.ID_MEDIASIZE = DICTIONARY_API_PRINTING.PAPERSIZE[RegDevmode.PaperSize]; PrintJob.N_MEDIASIZE = RegDevmode.PaperSize; PrintJob.ID_ORIENTATION = DICTIONARY_API_PRINTING.ORIENTATION[RegDevmode.Orientation]; PrintJob.N_ORIENTATION = RegDevmode.Orientation; PrintJob.N_COPIES = RegDevmode.Copies; PrintJob.ID_COLOR = DICTIONARY_API_PRINTING.COLORSPACE[RegDevmode.Color]; PrintJob.N_COLOR = RegDevmode.Color; PrintJob.ID_DUPLEX = DICTIONARY_API_PRINTING.DUPLEX_PAGEMODE[RegDevmode.Duplex]; PrintJob.N_DUPLEX = RegDevmode.Duplex; PrintJob.N_MEDIATYPE = (int)RegDevmode.MediaType; } // LeerDevmode
} //AnalizeEmf() /** \brief Analisis EMF Metafile record * \param EmfFile referencia al fichero de spool EMF * \param positionMetafileRecord Posición comienzo Metafile * \param Size tamaño del registro a analizar * \param ResumenEMR Objeto de la clase Tags para guardar un resumes de los Tags utilizados * \param PrintJob Estructura pasada por referencia para guardar las propiedades del trabajo de impresión * \details Se analizan los registros que guardan el contenido de las páginas a imprimir definidas mediante lenguaje EMF. */ private void AnalizeEMR(ref BinaryReader EmfFile, int positionMetafileRecord, int Size, ref Tags ResumenEMR, ref STRUCT_PRINT_JOB PrintJob) { int Position = positionMetafileRecord; int EmrRecord = 0; int EmrSize = 0; int EmrValue = 0; /// recorremos el registro EMFSPOOL con contenido de página identificando los registros tipo EMR de definición de contenido while (Position < (positionMetafileRecord + Size)) { /// Nos posicionamos en el siguiente registro EMF a analizar EmfFile.BaseStream.Seek(Position, SeekOrigin.Begin); EmrRecord = EmfFile.ReadInt32(); EmrSize = EmfFile.ReadInt32(); /// Se genera log con información de los registros EMF que se van identificando Log.Debug("Posición " + Util.MostrarHex((UInt32)(Position)) + " " + DICTIONARY_EMF.EMR_RECORD[EmrRecord] + ". Tamaño registro: " + Util.MostrarHex((UInt32)(EmrSize))); // Guardamos información del Tag Para presentar resumen al final del análisis ResumenEMR.Agregar(DICTIONARY_EMF.EMR_RECORD[EmrRecord]); if ((DICTIONARY_EMF.EMR_RECORD[EmrRecord] == "EMR_SETTEXTCOLOR") || (DICTIONARY_EMF.EMR_RECORD[EmrRecord] == "EMR_SELECTOBJECT") || (DICTIONARY_EMF.EMR_RECORD[EmrRecord] == "EMR_DELETEOBJECT")) { EmrValue = EmfFile.ReadInt32(); //Log.Debug(" " + Util.MostrarHex((UInt32)(Position + 8)) + " Value " + Util.MostrarHex((UInt32)(EmrValue))); } /// Si es un registro de cabecera EMR_HEADER lo analizamos utilizando el método AnalizeEmrHeader() if ((DICTIONARY_EMF.EMR_RECORD[EmrRecord] == "EMR_HEADER")) { byte[] ArrayEmrHeader = new byte[EmrSize]; EmfFile.BaseStream.Seek(Position, SeekOrigin.Begin); EmfFile.Read(ArrayEmrHeader, 0, EmrSize); // Analizamos el registro EMR_HEADER para obtener el tamaño de página AnalizeEmrHeader(ArrayEmrHeader, ref PrintJob, Position); } Position += EmrSize; } //while } // AnalizeEmfMetafileRecord()
} // Fin ReadStringJPL() /** \brief Analiza cadena JPL. * \details y si es necesario se actualiza la del Trabajo de Impresión. * \param StringJPL cadena JPL a analizar. * \param PrintJob struct por referencia con las propiedades del trabajo de impresión * \remarks (Fuente: recorrer un diccionario C#) * @see http://karlozarba.blogspot.com.es/2011/06/recorrer-un-dictionary-con-c.html */ private void AnalizeStringJPL(string StringJPL, ref STRUCT_PRINT_JOB PrintJob) { const string ESCAPE_CHARS = @";="" "; /// Comprobamos en el diccionario JPL si la cadena JPL a analizar contiene alguna propiedad de Trabajo de impresión foreach (KeyValuePair <string, ENUM_JPL.PROPERTY> Par in DICTIONARY_JPL.PROPERTY) { // La cadena JPL contiene un parámetro de análisis JPL if (StringJPL.Contains(Par.Key)) { // Buscamos la posición siguiente al valor llave en el diccionario de datos int VALUE_POSITION = StringJPL.IndexOf(Par.Key) + Par.Key.Length; // Con la siguiente instruccion calculamos realmente la posición donde se encuentra el valor VALUE_POSITION = this.PositionValueJPL(StringJPL, VALUE_POSITION); string Value = ""; bool Delimiter = false; // Recordamos si es un atributo delimitado por comillas if (StringJPL[VALUE_POSITION] == '"') { Delimiter = true; VALUE_POSITION++; } /// - Obtenemos el valor de la propiedad del Trabajo de Impresión for (int i = VALUE_POSITION; i < StringJPL.Length; i++) { if (!Delimiter) { if (ESCAPE_CHARS.Contains(StringJPL[i].ToString())) { // Forzamos condición de salida del bucle i = StringJPL.Length; } else { Value += StringJPL[i]; } } else { if (StringJPL[i] == '"') //Caracter delimitador { // Forzamos condición de salida del bucle i = StringJPL.Length; } else { Value += StringJPL[i]; } } //if } //for Log.Debug("Diccionario: '" + Par.Key + "' Valor de parámetro encontrado: " + Value); /// - Guardamos el valor de la propiedad del Trabajo de Impresión // Log.Debug("(Par.key, Par.Value): (" + Par.Key + ", " + Par.Value.ToString() + ")"); switch (Par.Value) { case ENUM_JPL.PROPERTY.ID_FUENTE: PrintJob.ID_FUENTE = "JPL/" + Value; Log.Info("Se estable como fuente de analisis: " + Value); break; case ENUM_JPL.PROPERTY.F_PRINTJOB: try { PrintJob.F_PRINTJOB = Value.Substring(6, 2) + "/" + Value.Substring(4, 2) + "/" + Value.Substring(0, 4) + " " + Value.Substring(8, 2) + ":" + Value.Substring(10, 2) + ":" + Value.Substring(12, 2); Log.Debug("AnalizeStringJPL. ENUM_JPL.PROPERTY.F_PRINTJOB: " + PrintJob.F_PRINTJOB); } catch (Exception e) { Log.Error(e + "La cadena '" + Value + "' no tiene formato de fecha"); } break; case ENUM_JPL.PROPERTY.ID_LOGIN: PrintJob.ID_LOGIN = Value; break; case ENUM_JPL.PROPERTY.ID_PRINTSERVER: PrintJob.ID_PRINTSERVER = Value; break; case ENUM_JPL.PROPERTY.ID_PRINTER: PrintJob.ID_PRINTER = Value; break; case ENUM_JPL.PROPERTY.ID_DOCUMENT: PrintJob.ID_DOCUMENT = Value; break; case ENUM_JPL.PROPERTY.N_LENGTH: PrintJob.N_LENGTH = Convert.ToInt32(Value); break; case ENUM_JPL.PROPERTY.N_WIDTH: PrintJob.N_WIDTH = Convert.ToInt32(Value); break; case ENUM_JPL.PROPERTY.ID_MEDIASIZE: PrintJob.ID_MEDIASIZE = Value; break; case ENUM_JPL.PROPERTY.ID_ORIENTATION: PrintJob.ID_ORIENTATION = Value; break; case ENUM_JPL.PROPERTY.ID_COLOR: PrintJob.ID_COLOR = Value; break; case ENUM_JPL.PROPERTY.ID_DUPLEX: PrintJob.ID_DUPLEX = Value; break; case ENUM_JPL.PROPERTY.ID_STATUS: PrintJob.ID_STATUS = Value; break; default: Log.Error("AnalizeStringJPL: Atributo JPL desconocido: " + Par.Value.ToString()); break; } //switch Log.Debug("La cadena JPL: '" + StringJPL + "' contiene el parámetro: '" + Par.Key + "'"); } //if. Contiene cadena del diccionario } //foreach //return StructJPL; } //AnalizeStringJPL()
} // Fin JPLSpool() /** \details * Buscar cadenas del bloque JPL en el fichero de spool de impresion. Se localizan cadenas que comienzan por: * - "%-12345X@PJL": Cabecera de los comandos JPL * - "@PJL": Instrucciones JPL. * * También guarda la posición de inicio y fin del Bloque PCLXL en las variable: * - BeginBlockPCLXL * - EndBlockPCLXL * \param PrintJob Estructura del tipo STRUCT_PRINT_JOB pasada por referencia en la que se guardan los detalles del trabajo de impresión obtenidos. */ public new void Analize(ref STRUCT_PRINT_JOB PrintJob) //string StringJPL, string PathFileJPL) { int PosicionJPL = 0; // Posición en el archivo de Spool // Para indicar si ya se ha encontrado la cabecera JPL bool HeaderJPLFound = false; // Para indicar si se ha encontrado el fin del contenido JPL/ bool FooterJPLFound = false; // Indica el tamaño del bloque que utilizamos para leer el fichero de Spool const int SIZE_BLOCKB_JPL = 1024 * 1024 * 64; // Se van cargando las instrucciones JPL contenidas en el fichero de spool para su analisis. string CadenaJPL; int i; // Objeto para fichero binario con el que hacemos el análisis del fichero de spool BinaryReader JPLFile; /// Se hacen busquedas de los siguientes Tags JPL en el fichero de Spool /// - Delimitador de bloque JPL byte[] ArrayJPLDelimitadorBloque = Util.ArrayCharToByte(_COMANDO_UEL.ToCharArray()); /// - Cabecera instrucción JPL byte[] ArrayJPLTag = Util.ArrayCharToByte(_JPL_COMANDO.ToCharArray()); // Indice de posición para Tag de cabecera JPL int PosicionJPLCabecera = 0; // Indice de posición para Tag de instrucción JPL int PosicionJPLTag = 0; // Se guardan bloques del fichero con contenido JPL para su análisis byte[] ArrayJPL; // = new byte[SIZE_BLOCKB_JPL]; // Objeto para abrir contenido PCLXL del fichero JPL/PCLXL PCLXLSpool MiPCLXLSpool; Log.Info("/*------------------------------------------------------------------------------------------*/"); Log.Info(" "); Log.Info(" "); Log.Info(" INICIO ANALISIS JPL "); Log.Info(" "); Log.Info(" "); Log.Info("/*------------------------------------------------------------------------------------------*/"); // Abrimos el fichero en la posición 0 y empezamos a recorrerlo try { JPLFile = new BinaryReader(File.Open(this.PathSpoolFile, FileMode.Open)); Log.Info("AnalisisCompletado JPL del fichero: " + this.PathSpoolFile); } catch (Exception e) { Log.Error("No se tiene acceso al fichero de Spool: " + this.PathSpoolFile); throw e; } // Inicializamos reloj para controlar el tiempo que tarda del análisis var Watch = new Stopwatch(); Watch.Start(); try { // Se analiza todo el contenido del fichero. Valor inicial de PosicionJPL=0 while (PosicionJPL < this.SizeFile) { //Nos posicionamos en el archivo JPL para leer un nuevo bloque de datos JPLFile.BaseStream.Seek(PosicionJPL, SeekOrigin.Begin); // Leemos nuevo bloque de datos if ((this.SizeFile - PosicionJPL) >= SIZE_BLOCKB_JPL) { // Todavía no hemos comprobado el fichero completo ArrayJPL = new byte[SIZE_BLOCKB_JPL]; ArrayJPL = JPLFile.ReadBytes(SIZE_BLOCKB_JPL); } else { // Quedan por leer menos bytes que el tamaño de bloque de lectura con el que trabajamos ArrayJPL = new byte[this.SizeFile - PosicionJPL]; ArrayJPL = JPLFile.ReadBytes(this.SizeFile - PosicionJPL); } /// Analizamos el bloque de datos en busca de Cabecera e instrucciones JPL for (i = 0; i < ArrayJPL.Length; i++, PosicionJPL++) { // Para la búsqueda de la cabecera JPL if ((ArrayJPL[i] == ArrayJPLDelimitadorBloque[PosicionJPLCabecera])) { if (PosicionJPLCabecera == (ArrayJPLDelimitadorBloque.Length - 1)) { // Hemos encontrado la cabecera JPL if (HeaderJPLFound) { // Segunda ocurrencia Cabecera JPL. Se cambia de PCLXL a JPL. Siguientes ocurrencias no se tienen en cuenta. if (!(FooterJPLFound)) { this.EndBlockPCLXL = PosicionJPL - ArrayJPLDelimitadorBloque.Length; } FooterJPLFound = true; } else { HeaderJPLFound = true; } // Volvemos a buscar otra nueva cabecera. Posicionamos la búsqueda al comienzo del Tag de cabecera a buscar PosicionJPLCabecera = 0; Log.Info("Posición " + Util.MostrarHex((UInt32)(PosicionJPL - ArrayJPLDelimitadorBloque.Length + 1)) + ": " + _COMANDO_UEL); } else { PosicionJPLCabecera++; } // End if } else { // Inicializamos la busqueda de la cabecera PosicionJPLCabecera = 0; } // End if búsqueda Tags Cabecera // Para la búsqueda Tags JPL if ((ArrayJPL[i] == ArrayJPLTag[PosicionJPLTag]) & (PosicionJPLCabecera == 0)) { if (PosicionJPLTag == (ArrayJPLTag.Length - 1)) { //Hemos encontrado el Tag JPL. Volvemos a inicializar la variable de control de búsqueda de Tag JPL. PosicionJPLTag = 0; // Obtenemos la instrucción JPL completa. CadenaJPL = ReadStringJPL(PosicionJPL - ArrayJPLTag.Length + 1, ref JPLFile); // Se analiza la instrucción JPL. AnalizeStringJPL(CadenaJPL, ref PrintJob); Log.Info("Posición " + Util.MostrarHex((UInt32)(PosicionJPL - ArrayJPLTag.Length + 1)) + ": " + CadenaJPL); // Instrucción JPL de cambio a modo PCLXL. Se guarda la posición de la cabecera PCLXL. if (JPLToPCLXL(CadenaJPL)) { this.BeginBlockPCLXL = PosicionJPL - ArrayJPLTag.Length + CadenaJPL.Length + 1; CadenaJPL = ReadStringJPL(this.BeginBlockPCLXL, ref JPLFile); Log.Info("Posición bloque PCLXL " + Util.MostrarHex((UInt32)(this.BeginBlockPCLXL)) + ": " + CadenaJPL); // El fichero de Spool utiliza PCLXL para guardar el trabajo de impresión. this.ContenidoPCLXL = true; } } else { PosicionJPLTag++; } // End if } else { // Inicializamos la busqueda de la cabecera PosicionJPLTag = 0; } // End if } // End for } //while } //try catch (Exception e) { JPLFile.Close(); Log.Info("El fichero de Spool no se ha podido analizar mediante lenguaje JPL"); throw e; } // Detenemos el reloj para controlar el tiempo que ha tardado del análisis JPL. Watch.Stop(); Log.Info("Tiempo transcurrido en Milisegundos del analisis JPL: " + Watch.ElapsedMilliseconds + " ms" + (char)Util._END_LINE1 + (char)Util._END_LINE1); Log.Debug("Cerramos el fichero analizado mediante lenguaje JPL"); JPLFile.Close(); Log.Info("/*------------------------------------------------------------------------------------------*/"); Log.Info(" "); Log.Info(" "); Log.Info(" FIN ANALISIS JPL"); Log.Info(" "); Log.Info(" "); Log.Info("/*------------------------------------------------------------------------------------------*/"); this.AnalisisCompletado = true; // Analizamos si tiene contenido PCLXL if (this.ContenidoPCLXL) { try { MiPCLXLSpool = new PCLXLSpool(this.PathSpoolFile, this.BeginBlockPCLXL, this.EndBlockPCLXL); MiPCLXLSpool.Analize(ref PrintJob); // Para control en la realización de pruebas this.AnalisisPCLXLCompletado = true; } catch (Exception e) { Log.Error("Error análisis PCLXL"); Log.Error(e); } } // Para control en la realización de pruebas this.AnalisisCompletado = true; } // Fin AnalizeJPL_PCLXL()
} //AnalizeSpool() /** \brief Guardar log propiedades del trabajo de impresión en B.D * \param PrintJob struct por referencia con las propiedades del trabajo de impresión * \return No devuelve nada */ private void SavePrintJob(ref STRUCT_PRINT_JOB PrintJob) { string SQL = ""; try { //int filas = 0; /// Guardamos las propiedades del trabajo de impresión en BD /// - Se construye la instrucción SQL de inserción SQL = "INSERT INTO SPOOL_PRINTJOBS(ID_JOBNAME, " + "ID_FUENTE, " + "N_JOB, " + "F_PRINTJOB, " + "ID_LOGIN, " + "ID_PRINTSERVER, " + "ID_PRINTER, " + "ID_DOCUMENT, " + "N_PAGES, " + "N_PAGES_PRINTED, " + "N_COLORPAGES, " + "N_LENGTH, " + "N_WIDTH, " + "ID_MEDIASIZE, " + "N_MEDIASIZE, " + "N_ORIENTATION, " + "N_COPIES, " + "ID_COLOR, " + "ID_DUPLEX, " + "ID_STATUS, " + "ID_ISPLOTTER, " + "ID_MEDIATYPE, " + "N_MEDIATYPE, " + "N_JOBSIZE) VALUES "; SQL += "('" + PrintJob.ID_JOBNAME + "', '" + PrintJob.ID_FUENTE + "', " + PrintJob.N_JOB + ", " + "TO_DATE('" + PrintJob.F_PRINTJOB + "', 'DD/MM/YYYY HH24:Mi:SS')" + ", '" + PrintJob.ID_LOGIN + "', '" + PrintJob.ID_PRINTSERVER + "', '" + PrintJob.ID_PRINTER + "', '" + PrintJob.ID_DOCUMENT + "', " + PrintJob.N_PAGES + ", " + PrintJob.N_PAGES_PRINTED + ", " + PrintJob.N_COLORPAGES + ", " + PrintJob.N_LENGTH + ", " + PrintJob.N_WIDTH + ", '" + PrintJob.ID_MEDIASIZE + "', " + PrintJob.N_MEDIASIZE + ", " + PrintJob.N_ORIENTATION + ", " + PrintJob.N_COPIES + ", '" + PrintJob.ID_COLOR + "', '" + PrintJob.ID_DUPLEX + "', '" + PrintJob.ID_STATUS + "', '" + PrintJob.ID_ISPLOTTER + "', '" + PrintJob.ID_MEDIATYPE + "', " + PrintJob.N_MEDIATYPE + ", " + PrintJob.N_JOBSIZE + ")"; Log.Info("Insert lanzado contra la BD:"); Log.Info(SQL); /// - Conectamos a la BD DBClient client = new DBClient(); /// - Lanzamos la instrucción SQL if (client.EjecutaSQL(SQL)) { Log.Info("Se guarda Información del trabajo de impresión en BD. INSERT correcto: "); } else { Log.Fatal("Falla el siguiente INSERT en BD: " + (char)13 + SQL); } /// - Cerramos la BD client.Close(); } catch (Exception e) { Log.Fatal(e.ToString() + (char)13 + SQL); } } //GuardarLog()