7/29/2012

A continuación mostramos un enlace donde indicamos cómo inicar y detener un servicio de Windows usando Visual C# .Net. Explicamos también cómo ejecutar una aplicación externa desde  nuestra aplicación C# como administrador:



A continuación mostramos un enlace donde explicamos cómo obtener la carga de la batería de un dispositivo con sistema Android usando Eclipse y Java. Mostramos cómo usar un TextView y un ProgresBarr en el proyecto Android en Eclipse para mostrar el nivel de carga de la batería tanto en una etiqueta como en una barra de progreso:

Obtener carga batería en aplicación Android Eclipse Java

7/27/2012

Explicamos en el siguiente enlace cómo ejecutar un determinado código Java cuando se cierra una aplicación Android. Para ello usamos Eclipse como IDE de desarrollo de aplicaciones Android:

Ejecutar código Java al cerrarse aplicación Android
En el siguiente enlace explicamos cómo reproducir un sonido mp3 o wav en una aplicación para dispositivos Android usando Java y el IDE Eclipse:

Reproducir sonido mp3 y wav en Android Java Eclipse

7/26/2012

En el siguietne enlace explicamos cómo hacer funcionar la Barra de Google  en el navegador Mozilla Firefox a partir de su versión 14:

Barra de Google en Mozilla Firefox 14

7/18/2012

Instalar monitor de red gratuito con PRTG Network Monitor



Tutorial donde explicamos cómo montar un servidor de monitorización de red gratuito usando PRTG Network Monitor. Usaremos la versión freeware de PRTG, esta versión gratuita tiene un límite de 10 sensores como máximo. PRTG Network Monitor es el sucesor del antiguo software de monitorización Paessler Router Traffic Grapher. Realizaremos la instalación del monitor en un equipo con Microsoft Windows 7 y monitorizaremos routers, switchs, servidores Linux y Windows, bases de datos MySQL y PostgreSQL.



PRTG Network Monitor

PRTG Network Monitor (PRTG, sucesor de Paessler Router Traffic Grapher) es un software de monitorización de red de la empresa Paessler AG.
PRTG se ejecuta en Windows y utiliza los protocolo SNMP, sniffing de paquetes, WMI, IP SLA y NetFlow para obtener los datos necesarios para las estadísticas y sensores.
PRTG Network Monitor dispone de dos versiones:
  • Comercial, de pago, sin límites de uso.
  • Freeware, con la posibilidad de añadir hasta diez sensores como máximo.
Existen multitud de monitores de red y de ancho de banda como: Nagios (freeware), Pandora FMS (freware y comercial), NetXMS (freeware), OpenNMS (freeware), Opsview (freeware y comercial), Zenoss (freeware y comercial), Nimsoft Monitor (comercial), GroundWork Monitor Core (free con limitaciones y comercial), Ganglia Monitoring System (freeware), FreeNATS Network Monitor (freeware), PacketTrap (comercial), Munin (freeware), etc.
 

Descargar e instalar PRTG Network Monitor

Abriremos una navegador web y accderemos a la página oficial de PRTG Network Monitor, accederemos a la URL:
http://www.paessler.com/prtg/download
Descargaremos la versión "Freeware Download" (Limited to 10 Sensors, Free Forever), tras pulsar en la descarga nos redireccionará a una página para obtener la clave de licencia, introduciremos una dirección de correo electrónico válida y pulsaremos "Get Free License Key":
Descargar e instalar de PRTG Network Monitor
Nos mostrará una nueva página con la clave de licencia que deberemos anotar para, posteriormente, activar nuestro software instalado con esta clave:
Descargar e instalar de PRTG Network Monitor
Descomprimiremos el fichero "prtg.zip" de (90MB) descargado anteriormente, una vez descomprimido ejecutaremos el fichero: PRTG Network Monitor 12.2.2.2210 Setup Freeware and Trial (Stable).exe, es conveniente ejecutarlo como administrador, pulsando con el botón derecho del ratón sobre el fichero y seleccionando "Ejecutar como administrador":
Descargar e instalar de PRTG Network Monitor
Seleccionaremos el idioma de instalación y pulsaremos "Aceptar":
Descargar e instalar de PRTG Network Monitor
El asistente para instalar el monitor de red PRTG Network Monitor nos avisará de que la versión que estamos instalado es gratuita, pulsaremos "Sí":
Descargar e instalar de PRTG Network Monitor
Se iniciará el asistente para instalar PRTG Network Monitor, pulsaremos "Siguiente":
Descargar e instalar de PRTG Network Monitor
Leeremos los términos de licencia, si estamos de acuerdo marcaremos "Acepto el acuerdo" y pulsaremos "Siguiente":
Descargar e instalar de PRTG Network Monitor
Introduciremos una dirección de correo electrónico para envío de notificaciones de alarmas del servidor de monitorización (podremos configurar esto una vez instalado el servidor de monitorización):
Descargar e instalar de PRTG Network Monitor
Introduciremos la clave de licencia obtenida en pasos anteriores y pulsaremos "Siguiente":
Descargar e instalar de PRTG Network Monitor
Seleccionaremos la carpeta de instalación y pulsaremos "Siguiente":
Descargar e instalar de PRTG Network Monitor
Tras la instalación de PRTG Network Monitor se abrirá el navegador Google Chrome (si lo tenemos instalado), si no lo tenemos instalado se abrirá el navegador por defecto y se iniciará el asistente de configuración de PRTG Network Monitor.

Configuración inicial de PRTG Network Monitor

Tras la instalación de PRTG Network Monitor se abrirá el navegador y se accederá a la URL:
http://IP_servidor_monitorizacion:8080
Se iniciará el asistente de configuración inicial, pulsaremos "Start Guru" para realizar una configuración avanzada:
Configuración inicial de PRTG Network Monitor
El asistente nos indicará si queremos activar el acceso mediante https, en nuestro caso no lo activaremos de momento, pulsaremos "No":
Configuración inicial de PRTG Network Monitor
Introduciremos ahora los datos de acceso para administración de PRTG Network Monitor, en concreto el nick (nombre de usuario), el correo electrónico y la contraseña:
Configuración inicial de PRTG Network Monitor
Si tenemos credenciales de acceso específicas para el protocolo SNMP en nuestros equipos podremos especificarlas aquí marcando "Yes, I need to enter my own credentials" si no marcaremos "No, all my SNMP-enabled network devices use default credentials" y pulsaremos "Skip":
Configuración inicial de PRTG Network Monitor
Si tenemos algún servidor de virtualización con VMware ESX o Citrix XenServer marcaremos "Yes, I have VMware and/or XEN servers", si no marcaremos "No, I do not use virtualization based in VMware or XEN". Si marcamos la opción de que sí tenemos el servidor introduciremos los datos de acceso (usuario, contraseña y protocolo de acceso). Si hemos marcado que sí tenemos servidores VMware o XEN pulsaremos "Save & Next", si no pulsaremos "Skip":
Configuración inicial de PRTG Network Monitor
Si tenemos servidores con sistema operativo Linus o OSX podremos indicar en este paso de la configuración los datos de acceso y protocolo (WBEM, SSH) marcaremos "Yes, I have servers running on Linux or OSX". Por supuesto todos estos datos de acceso se establecerán como predeterminados pero se podrán indicar (una vez finalizada la configuración inicial) datos de acceso específicos por cada servidor (aparato) a monitorizar:
Configuración inicial de PRTG Network Monitor
Introduciremos los datos de acceso a Internet, puerta de enlace (Default Gateway), DNS 1 y DNS 2 y pulsaremos "Save & Netxt":
Configuración inicial de PRTG Network Monitor
Si disponemos de uno o varios controladores de dominio Active Directory podremos indicarlos en este paso de la configuración. También podremos añadir los servidores de nuestra organización. Aunque no es necesario en este paso pues posteriormente se podrán añadir servidores y servicios a monitorizar. El asistente de instalación de PRTG Network Monitor iniciará un autodescubrimiento para buscar todos los equipos y servicios estándar de la red donde hayamos instalado el monitor:
Configuración inicial de PRTG Network Monitor
También podremos indicar sitios web a monitorizar:
Configuración inicial de PRTG Network Monitor
Si tenemos algún servicio Cloud (Google Search, Google Docs, Google Mail, Office 365, Salesforce, Dropbox, iCloud, Facebook, Twitter, Skype) podremos activar su monitorización marcando "Yes":
Configuración inicial de PRTG Network Monitor
Indicaremos a continuación la subred en la que establecerá el servicio de autodescubrimiento, de forma que PRTG realizará un escaneo en busca de dispositivos y posibles servicios estándar para añadir los sensores de cada dispositivo encontrado (servidores, equipos clientes, servidores de base de datos, servidores de correo, servidores web, servidores de mail, switchs, router, impresoras, etc.):
Configuración inicial de PRTG Network Monitor
Por último pulsaremos en "OK! Let me view my new sensors!", si se ha iniciado el autodescubrimiento ya empezarán a aparecer aparatos y sensores en el "Resumen" de la consola web de PRTG Network Monitor, además de los que hayamos introducido en le proceso de configuración anterior:
Configuración inicial de PRTG Network Monitor
El estado del autodescubrimiento podremos verlo en el menú "Configuración" - "Estado del PRTG":
Configuración inicial de PRTG Network Monitor
En el botón "Pendientes" de la partes superior derecha podremos comprobar los dispositivos y sensores detectados en el autodescubrimiento, pendientes de ser confirmados como sensor a monitorizar. Pulsando en "Confirmar" el sensor o dispositivo pasará a ser monitorizado:
Configuración inicial de PRTG Network Monitor
Una vez iniciada la monitorización de los sensores y dispositivos que queramos, empezarán a aparecer algunas alarmas si algo "no va bien", por ejemplo, en nuestro caso, PRTG Network Monitor nos avisa de que el disco duro C de uno de los equipos monitorizados tiene menos de un 10% de espacio libre:
Configuración inicial de PRTG Network Monitor
Desde el menú "Pág. princ.":
Configuración inicial de PRTG Network Monitor

 

Instalar Consola Enterprise PRTG (Windows GUI)

Podremos acceder a algunas de las opciones principales de PRTG Network Monitor como volver a abrir el asistente de configuración (Run Welcome Guru), descargar la consola de Enterprise PRTG Network Monitor (aplicación de escritorio), instalar los apps para smartphones, configurar el descubrimiento automático, etc.:
Instalar Consola Enterprise PRTG (Windows GUI)
Por ejemplo, desde cualquier equipo de la red, accediendo a la consola web de PRTG podremos instalar la consola Enterprise pulsando en "Descargar la consola Enterprise" en la ventana anterior y descargando e instalando la aplicación pulsando en "Descarga: Consola Enterprise PRTG":
Instalar Consola Enterprise PRTG (Windows GUI)
Una vez descargado el fichero "PRTG_Enterprise_Console_Installer.exe" lo ejecutaremos e instalaremos:
Instalar Consola Enterprise PRTG (Windows GUI)
Una vez instalada la ejecutaremos desde "Inicio" - "PRTG Network Monitor" - "PRTG Enterprise Console":
Instalar Consola Enterprise PRTG (Windows GUI)
Enterprise PRTG Network Monitor detectará el servidor de monitorización (si no lo autodescubre podremos agregarlo manualmente), pulsaremos en "Editar" para cambiar usuario y contraseña de acceso:
Instalar Consola Enterprise PRTG (Windows GUI)
Introduciremos IP, puerto, usuario y contraseña para el servidor de monitorización PRTG al que nos conectaremos:
Instalar Consola Enterprise PRTG (Windows GUI)
Nos mostrará una ventana que se superpone sobre las demás con el estado de los sensores y dispositivos monitorizados. Esta ventana de aviso aparecerá superpuesta cada vez que se detecte una nueva alerta:
Instalar Consola Enterprise PRTG (Windows GUI)
Desde la consola podremos ver las mismas opciones que vía web, por ejemplo los sensores y dispositivos autodescubiertos pendientes de confirmación. Podremos confirmar uno de ellos o todos pulsando con el botón derecho y seleccionando "Confirmar objeto pendiente seleccionado":
Instalar Consola Enterprise PRTG (Windows GUI)
Nos avisará si estamos seguros de confirmar el objeto pendiente, pulsaremos "OK":
Instalar Consola Enterprise PRTG (Windows GUI)
Desde la pestaña "Aparatos" podremos comprobar todos los aparatos (dispositivos, servidores, equipos, impresoras, switchs, routers, ...) autodescubiertos y confirmados o añadidos manualmente, así como el estado de cada sonda de cada dispositivo:
Instalar Consola Enterprise PRTG (Windows GUI)

Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG

Para añadir un nuevo sensor de forma manual, por ejemplo añadiremos la monitorización de una base de datos MySQL instalada en el aparato "PROYECTOA". Seleccionaremos el dispositvo que contiene el servicio o sensor a monitorizar, pulsaremos con el botón derecho y seleccionaremso "Añadir sensor", buscaremos el tipo de sensor de entre los disponibles o bien pulsaremos en alguna de las opciones para filtrar: disponibilidad/tiempo disponible, ancho de banda/tráfico, speed/performance, uso de CPU, uso de disco, uso de memoría, parámetros hardware, infraestructura de rd, sensores personalizados, Windows, Linux, MacOS, sistema de virtualización, servidor de archivos, servidor de correo, servidor SQL, ping, SNMP, WMI, HTTP, SSH, Sniffer de paquetes, NetFlow, sFlow, jFlow:
Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG
. En nuestro caso buscaremos "MySQL", pulsarmos "Añadir esto" en el sensor "MySQL":
Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG
Introduciremos los datos para el nuevo sensor de base de datos MySQL, los más importantes:
  • Nombre del sensor: nombre descriptivo (corto a ser posible) del sensor, por ejemplo "MySQL".
  • Identificadores: para búsquedas posteriores, por ejemplo "sqlsensor", "mysql".
  • Prioridad: es necesario establecer este valor adecuadamente, si el sensor es importante le asignaremos una alta prioridad, sino la podremos bajar. Servirá, entre otras cosas, para organizar el objeto en futuras listas.
  • Puerto: si el puerto de nuestro servidor MySQL es el de defecto marcaremos "Automático", si es diferente marcaremos "Manual" e introduciremos el puerto para conexión con MySQL.
  • Base de datos: nombre de alguna de las bases de datos (catálogos) de MySQL.
  • Usuario: usuario con permisos de acceso a esta base de datos.
  • Contraseña: contraseña para el usuario de MySQL anterior.
  • Expresión SQL: PRTG permite una gran granularidad a nivel de sensor, en este caso nos permite incluso ejecutar consultas SQL personalizadas y decidir si el sensor falla cuando se produzca un determinado resultado en una consulta SQL. Si no queremos llegar a este nivel de detalle, no introduciremos expresión SQL.
Una vez introducidos los datos para el nuevo sensor pulsaremos en "Continuar":
Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG
Enterprise PRTG quedará iconizado en el área de notificación de Windows, cada vez que se monitorice una nueva alarma relacionada con el mal funcionamiento de algún sensor nos mostrará una ventana emergente (que hemos mostrado anteriormente):
Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG
Podremos añadir y renombrar todos los aparatos autodescubiertos, cambiarlos de grupo, añadir nuevos grupos, etc.:
Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG
Pulsando en cualquier aparato podremos ver todos sus sensores, estado, gráficas, prioridad, etc. Por ejemplo, nuestro equipo PROYECTOA tiene activos los siguientes sensores: PING, HTTP, espacio en disco, carga CPU, uso de memoria, MySQL:
Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG
Pulsando en cualquier sensor podremos ver el detalle de éste, por ejemplo, pulsando en el sensor añadido manualmante "MySQL" podremos ver todos los datos de estado, gráficas de tiempo de respuesta, tiempo de parada, etc.:
Añadir un nuevo sensor para monitorizar un servidor de base de datos MySQL desde Enterprise PRTG

Añadir sensor servidor base de datos PostgreSQL en consola web PRTG

Desde la consola web de PRTG, pulsando en el servidor o aparato al que le añadiremos el sensor, en la parte inferior pulsaremos en "Añadir sensor":
Añadir sensor servidor base de datos PostgreSQL en consola web PRTG
Introduciremos los datos para el nuevo sensor, como ya hemos hecho anteriormente. La única diferencia será que en el tipo de sensor seleccionaremos "ADO SQL", para este tipo de sensor deberemos indicar una cadena de conexión a la base de datos ADO y tener instalar el driver ODBC para el motor de base de datos a monitorizar, en nuestro caso PostgreSQL. En el siguiente artículo explicamos cómo instalar un driver ODBC para PostgreSQL:
Para este sensor indicaremos en "Connectionstring" la cadena de conexión para el origen de datos ODBC a monitoriar, con el formato:
DRIVER={nombre_del_driver_ODBC}; SERVER=IP_servidor_BD; PORT=puerto_servidor_BD; UID=Usuario_base_datos; PWD=contraseña_usuario; DATABASE=nombre_base_datos
De la misma forma que hemos explicado para el sensor de MySQL, para este sensor SQL podremos establecer el nivel de granularidad que queramos o bien por servicio (conexión) o bien por resultado de expresión SQL:
Añadir sensor servidor base de datos PostgreSQL en consola web PRTG
Para comprobar la eficacia de PRTG Network Monitor hemos detenido el servidor de PostgreSQL, en cuestión de segundos nos ha indicado la alarma correspondiente en el sensor:
Añadir sensor servidor base de datos PostgreSQL en consola web PRTG

Resumen de características de PRTG Network Monitor, conclusiones

PRTG Network Monitor permite monitorizar cualquier dispositivo de la red de una organización que disponga de IP: impresoras, servidores, equipos, switchs, routers, webs, etc. y permite monitorizar cientos de sensores (servicios) como indiamos más abajo.
Si tenemos instalado Google Chrome, activando las "Chrome Desktop Notifications" no necesitaremos instalar Enterprise PRTG Windows GUI para las notificaciones emergentes.
PRTG permite varios métodos de envío de notificaciones de alerta: correo electrónico, añadir entrada al log de eventos, enviar mensaje Syslog, enviar Trap SNMP, enviar SMS, ejecutar acción HTTP, ejecutar programa, enviar Amazon Simple Notificaion Service Message.
Sin duda, tras las pruebas realizadas en nuestro laboratorio, PRTG Network Monitor es uno de los sistemas de monitorización de dispositivos, servicios, aparatos más avanzados del mercado. Es altamente configurable, de sencillo manejo, con una interfaz tanto web como aplicación amigable y sencilla.
La única nota negativa de PRTG Network Monitor es que el servidor de monitorización no está disponible para Linux, sólo para Windows. El otro inconveniente es que la versión gratuita sólo admite hasta 10 sensores.
A continuación mostramos los sensores disponibles directamente para PRTG Network Monitor:
  • Ping: monitoriza conectividad usando Ping.
  • Jitter de Ping: regresa el valor de jitter estadístico de Pings del aparato nodriz.
  • Traceroute: provee el numero de hops a el aparato nodriz y alerta si la route ha cambiado.
  • Puerto: revisa la disponibilidad de servicios de red conectandose al puerto TCP/IP.
  • HTTP: monitoriza un servidor web usando HTTP (Hypertext Transfer Protocol).
  • HTTP Avanzado: monitoriza un servidor web usando HTTP (inclusive autentificacion, chequeo de contenido, etc.).
  • HTTP Transaccion: realiza una transaccion en un sitio de red usando una serie de URLs.
  • HTTP Contenido: monitoriza un valor de regreso de una requisicion HTTP.
  • HTTP Pagina Web Completa: monitoriza el tiempo de descarga completa de una pagina web incluyendo imagenes, etc.
  • Caducidad de certificado HTTP SSL: regresa el numero de dias que quedan antes que el certificado SSL de un servidor HTTPS expire.
  • Valor HTTP XML/REST: extrae un archivo XML de un servidor http y regresa el valor de un nodo XML.
  • FTP: monitoriza servidores FTP (File Transfer Protocol) y FTPS (FTP via SSL).
  • Numero de archivos en el servidor FTP: regresa el numero de archivos en un servidor FTP.
  • TFTP: monitoriza un servidor TFTP (Trivial FTP).
  • DNS: revisa un servidor DNS (Domain Name Service).
  • RADIUS: monitoriza servidores RADIUS (remote authentication dial-in user service).
  • LDAP: monitoriza servicios de directorio LDAP.
  • SNTP: monitoriza un servidor NTP (Network Time Protocol).
  • SMTP: monitoriza servidores de correo basados en SMTP (Simple Mail Transfer Protocol).
  • POP3: monitoriza servidores de correo basados en POP3 (Post Office Protocol V3).
  • SMTP&POP3 Round Trip: monitoriza el tiempo necesario para que un correo llegue a un buzon POP3 despues de ser enviado via SMTP.
  • IMAP: monitoriza servidores de correo basados en IMAP (Internet Message Access Protocol).
  • SMTP&IMAP Round Trip: monitoriza el tiempo necesario para que un correo llegue a un buzon IMAP despues de ser enviado via SMTP.
  • Cuenta de correo POP3: este sensor cuenta el numero de mensajes de correo en un buzon de POP3.
  • RDP (Remote Desktop): monitoriza servicios de conexion remota (RDP, clientes Terminal Services).
  • SSH carga promedio: monitoriza promedios de carga de un sistema Linux/Unix o Mac OS usando SSH.
  • SSH informacion de memoria: monitoriza el uso de memoria de un sistema Linux/Unix o Mac OS usando SSH.
  • SSH disco libre: monitoriza espacio libre en discos de un sistema Linux/Unix usando SSH.
  • SSH INodes libres: monitoriza INodes dispnibles en un disco de un sistema Linux/Unix o Mac OS usando SSH.
  • SNMP carga promedio Linux: monitoriza promedios de carga de sisteam de Linux/Unix usando SNMP.
  • SNMP informacion de memoria Linux: monitoriza el uso de memoria de un sistema Linux/Unix usando SNMP.
  • SNMP disco libre Linux: monitoriza espacio libre en discos de un sistema Linux/Unix usando SNMP.
  • SNMP trafico: monitoriza ancho de banda y trafico de servidores, ordenadores, switches, etc. via SNMP.
  • Biblioteca SNMP: monitoriza un aparato usando SNMP y una MIB compilada ("Biblioteca SNMP").
  • Disponibilidad SNMP: monitoriza el tiempo activo de un aparato usando SNMP.
  • SNMP personalizado: monitoriza un valor numerico de una OID especifica usando SNMP.
  • SNMP Custom String: monitoriza una cadena de una OID especifica usando SNMP.
  • Cisco IP SLA: monitoriza parametros de red VoIP usando IP SLA de Cisco (usa SNMP).
  • WMI carga de procesador: monitoriza cargas de procesador mediante WMI.
  • WMI memoria: monitoriza memoria de sistema disponible mediante WMI.
  • Tiempo disponible WMI: monitoriza la disponibilidad de un sistema Windows usando WMI.
  • WMI disco libre (discos multiples): monitoriza espacio libre de un o todos los discos locales (un canal por disco).
  • WMI Volumen: monitoriza espacio de disco libre en un disco o un volumen logico usando WMI.
  • WMI tarjeta de red: monitoriza uso de ancho de banda y trafico a traves de la tarjeta de red usando WMI.
  • WMI pagefile: monitoriza el uso de pagefiles Windows mediante WMI.
  • WMI servicio: monitoriza un servicio mediante WMI.
  • WMI Share: monitoriza un recurso compartido de un sistema Windows usando WMI.
  • WMI Terminal Services XP/Vista/2k3: monitoriza el numero de sesiones en un servidor Windows Terminal Services usando WMI.
  • WMI Terminal Services (Win2008): monitoriza el numero de sesiones en un servidor Windows Terminal Services usando WMI.
  • WMI proceso: monitoriza un proceso mediante WMI.
  • WMI event log: monitoriza entradas en un Event Log mediante WMI.
  • WMI archivo: monitoriza un archivo mediante WMI.
  • WMI personalizado: realiza una requisicion personalizada de tipo WMI.
  • WBEM Personalizado: ejecuta una gestion WBEM personalizada.
  • Log de eventos (Windows API): monitoriza entradas de log de eventos usando la API de Windows.
  • WMI Microsoft SQL Server 2005: monitoriza el rendimiento de una instancia de servidor Microsoft SQL 2005.
  • WMI Microsoft SQL Server 2008: monitoriza el rendimiento de una instancia de servidor Microsoft SQL 2008.
  • WMI IIS 6.0 SMTP Enviados: monitoriza el numero de correos enviados de un servicio SMTP IIS 6.0 (Exchange 2003).
  • WMI IIS 6.0 SMTP Recibidos: monitoriza el numero de correos recibidos de un servicio SMTP IIS 6.0 (Exchange 2003).
  • Microsoft SQL: monitoriza una base de datos de servidor Microsoft SQL.
  • MySQL: monitoriza una base de datos de servidor MySQL.
  • Oracle SQL: monitoriza una base de dates de servidor Oracle.
  • ADO SQL: monitoriza una base de datos usando una conexion ADO.
  • Hardware de host VMware (WBEM): monitoriza informacion de hardware de un servidor ESX/ESXi usando WBEM.
  • Amazon CloudWatch: monitoriza la efectividad de una instancia EC2 usando Amazon CloudWatch.
  • EXE/Script: inicializa ejecutables (EXE, DLL) o scripts (archivos batch, VBScript, Powershell) que regresan texto
  • EXE/Script Avanzado: Runs EXE/DLL or a script (batch file, VBScript, Powershell) which returns XML.
  • Citrix XenServer Virtual Machine: monitors a virtual machine on a Citrix XenServer version 5.0 or later.
  • Citrix XenServer Host: monitors a Citrix XenServer host version 5.0 or later.
  • SSH VMWare ESX(i) Sensor de disco: monitoriza espacio libre en discos de un sistema VMware ESX(i) usando SSH.
  • NetFlow V5: monitoriza un switch usando NetFlow version 5.
  • NetFlow (Personalizado): monitoriza un switch usando NetFlow version 5 (configurable).
  • NetFlow V9: monitoriza switches usando NetFlow version 9.
  • NetFlow V9 (Personalizado): monitoriza switches usando NetFlow version 9 (configurable).
  • sFlow: monitoriza aparatos compatibles von sFlow v5.
  • sFlow (Personalizado): monitoriza aparatos compatibles von sFlow v5 (adaptable).
  • jFlow V5 (personalizado): monitoriza un switch usando jFlow V5 (configurable).
  • jFlow V5: monitoriza un switch usando jFlow V5.
  • AVM FRITZ!Box WAN Interface: m onitors the internet connection traffic of an AVM Fritz!Box.
  • Google Analytics: pulls data from Google Analytics.
  • SNMP Cisco ASA VPN Traffic: monitors the traffic for IPsec VPN tunnels on a Cisco Adaptive Security Appliance.
  • SNMP Cisco ASA VPN Connections: monitors VPN connections on a Cisco Adaptive Security Appliance.
  • WMI IIS Application: monitors a Microsoft Internet Information Services installation using WMI.
  • WMI SharePoint Process: monitors processes on a Microsoft SharePoint server using WMI.
  • Ultima actualizacion de Windows: indica la ultima vez que la actualizacion de Windows fue ejecutada en la maquina especificada.
  • Usuarios registrados en Windows: regresa el numero de usuarios actualmente registrados en el aparato nodriz
  • WMI Version de Windows: este sensor discierne la version de Windows del aparato nodriz.
  • Queue de impresion Windows: regresa el numero de pendientes de un queue de impresion.
  • Blacklist de IP en DNS: este sensor revisa la direccion IP de un aparato nodriz, comparandola con un numero de servidores Blacklist.
  • Errores de replicacion de directorio activo: revisa controladores de dominio Windows por errores de replicacion
  • Largo de queue de Windows MSMQ: este sensor cuenta el numero de mensajes en una MSMQ.
  • WMI Remote Ping: remotely monitors the connectivity between a system running Windows and an other device, using Ping and WMI.
  • SIP Options Ping: monitors connectivity for a SIP server using SIP options "Ping".
  • Disco libre share: monitoriza espacio de disco libre de shares SMB (Windows/Samba).
  • Estatisticas WSUS: this sensor retrieves various WSUS statistics. WSUS 3.0 Administration Console needs to be installed on the probe system.
  • Archivo: monitoriza un archivo (disponibilidad, edad, tamaño, cambios) usando SMB.
  • Carpeta: monitoriza una carpeta (disponibilidad, edad, tamaño, numero de archivos, cambios) usando SMB.
  • Contenido de archivo: returns the last occurrence of a specified string in a file, e.g. a log file.
  • Windows Scheduled Task: returns the number of minutes since the last run of the specified task.
  • INI File Content Check: returns the value from the field of an ini-file.
  • Pingdom: regresa el tiempo de respuesta de la revision de Pingdom.
  • Sensor Factory: generar sus propios sensors con canales basados en los datos de sensores existentes
  • WMI disco logico: monitoriza tiempo de lectura/escritura, bytes acumulados, cola, IO particionad, etc. en particiones logicas de disco.
  • WMI disco fisico: monitoriza tiempo de lectura/escritura, bytes acumulados, cola, IO particionad, etc. en discos fisicos.
  • WMI Datos vitales de sistema (V2): monitoriza paramteros vitales del sistema usando WMI (procesador, memoria, disco, red).
  • WMI Security Center: monitoriza el estado de software de seguridad como viene reportado del Microsoft Security Center.
  • SNMP HP LaserJet Hardware: monitoriza contadores de una impresora HP Laserjet.
  • SNMP Dell Hardware: monitoriza contadores de un ordenador Dell.
  • SNMP APC Hardware: monitoriza contadores de hardware APC UPS.
  • WMI servidor Exchange: monitoriza un servidor Microsoft Exchange usando WMI.
  • ZEN: the ZEN of PRTG.
  • TI Verde: we all want Green IT.
  • Maquina virtual Hyper-V: monitoriza una maquina virtual en un servidor Hyper-V.
  • Servidor Hyper-V Host: monitoriza un servidor Hyper-V.
  • Adaptador de red virtual Hyper-V: monitoriza un adaptador de red virtual Hyper-V.
  • Aparato de almacenamiento virtual Hyper-V: monitoriza un aparato de almacenamiento virtual Hyper-V.
  • WMI UTC Time: monitors the UTC Time of a device using WMI. The value is compared to the time of the PRTG Core Service.
  • Registro: monitoriza un valor en el registro.
  • Uso de disco de contenedor Virtuozzo: monitoriza el uso de disco de un contenedor de un servidor Virtuozzo.
  • Red de contenedor Virtuozzo: monitoriza trafico de red de un contenedor de servidor Virtuozzo.
  • VMware Host Performance (SOAP): monitors the performance of a VMware host server version 4.0 or later, or VMware Workstation 8.0 or later, using SOAP.
  • VMware Virtual Machine (SOAP): monitors virtual machines on a VMware host server version 4.0 or later using SOAP.
  • VMware Host Hardware Status (SOAP): monitors the hardware health status of a VMware host server version 4.0 or later using SOAP.


 

Artículos relacionados


Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del Proyecto AjpdSoft.

7/17/2012

Extraer texto y metadatos de fichero PDF con Visual C# .Net y iTextSharp



Explicamos en este tutorial cómo extraer el texto y los metedatos de múltiples ficheros PDF. Mostramos cómo desarrollar una aplicación de indexación del texto y metadatos de ficheros PDF de forma nativa (sin necesidad de tener instalado software de terceros). Explicamos paso a paso cómo obtener el texto de un fichero PDF y sus metadatos (asunto, palabras clave, etc.) usando la DLL gratuita iTextSharp y el lenguaje de programación Microsoft Visual C# .Net 2010. Publicamos una aplicación completa de ejemplo con el código fuente en VB.Net: AjpdSoft Indexar Texto PDF C# iTextSharp.


 

Descarga del componente gratuito iTextSharp

Para desarrollar una aplicación de indexación del texto y metadatos de ficheros PDF (portable document format ó formato de documento portátil) usaremos la librería gratuita iTextSharp, por lo tanto necesitaremos descargar el fichero de esta librería dll. Accederemos a la URL:
http://sourceforge.net/projects/itextsharp
Descargaremos la versión más reciente de iTextSharp (iText#), en nuestro caso: iTextSharp 5.2.1. Se descargará el fichero itextsharp-all-5.2.1.zip, lo descomprimiremos. Este fichero contiene, a su vez, los siguientes ficheros comprimidos:
  • itextsharp-dll-cores-5.2.1.zip
  • itextsharp-dll-xtra-5.2.1.zip
  • itextsharp-src-core-5.2.1.zip
  • itextsharp-src-xtra-5.2.1.zip
iTextSharp está desarrollado en Microsoft Visual C# y, además, la descarga anterior incluye el código fuente completo (itextsharp-src-core-5.2.1.zip). En nuestro caso usaremos la DLL ya compilada de iTextSharp por lo que descomprimiremos el fichero "itextsharp-dll-cores-5.2.1.zip" que contiene el fichero itextsharp.dll, este será el fichero necesario para trabajar con ficheros PDF usando Microsoft Visual C#. Copiaremos este fichero a la carpeta que queramos (por ejemplo la raíz de nuestros proyectos). Más adelante deberemos seleccionarlo desde nuestro proyecto Visual C#:
Descarga del componente gratuito iTextSharp

Instalación de Microsoft Visual Studio .Net

Para desarrollar la aplicación que nos permita trabajar con ficheros PDF usaremos el lenguaje de programación Microsoft Visual C#. En este tutorial obtendremos el texto de los ficheros PDF seleccionados y lo guardaremos en una base de datos para su posterior consulta.
Usaremos la suite de desarrollo Microsoft Visual Studio .Net. En el siguiente tutorial explicamos cómo instalar esta suite de desarrollo:

Indexar texto fichero PDF con C# C Sharp y iTextSharp

A continuación explicaremos cómo crear un proyecto o solución en Microsoft Visual C# .Net para extraer el texto de los ficheros PDF seleccionados y mostrarlo en pantalla o guardarlo en una tabla de una base de datos para su posterior consulta y tratamiento. Para ello abriremos Visual Studio .Net, pulsaremos en el menú "Archivo" - "Nuevo proyecto":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Seleccionaremos en la parte izquierda "Otros lenguajes" - "Visual C# ", en la parte derecha seleccionaremos "Aplicación de Windows Forms" e introduciremos el nombre del proyecto, por ejemplo "AjpdSoftIndexarTextoFicherosPDF":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Agregaremos la referencia a iTextSharp, para ello pulsaremos en el menú "Proyecto" - "Agregar referencia":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Pulsaremos en la pestaña "Examinar" y seleccionaremos el fichero "iTextSharp.dll" descargado anteriormente:
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Añadiremos los "using" al proyecto, para ello pulsaremos en el menú "Ver" - "Código" y agregaremos las referencias necesarias :
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Al principio agregaremos el siguiente código:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Data.Odbc;
Añadiremos los siguientes componentes al formulario principal de nuestra aplicación para extraer el texto y metadatos de ficheros PDF: ChekedListBox, Button, GroupBox, TabControl, StatusStrip, OpenFileDialog, SaveFileDialog, etc.:
Indexar texto fichero PDF con C# C Sharp y iTextSharp
En la pestaña "Indexar a Base de datos" añadiremos estos otros componentes:
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Añadiremos un segundo formulario (Form) a nuestra aplicación, en él mostraremos la consulta SQL necesaria para crear la tabla donde guardar el texto extraído de los ficheros PDF. Para ello pulsaremos en el menú "Proyecto" - "Agregar Windows Forms":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Seleccionaremos "Windows Forms", introduciremos un nombre para el fichero por ejemplo "formSQL.cs" y pulsaremos "Agregar":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
En el nuevo formulario agregaremos los siguientes componentes:
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Agregaremos también un par de clases, una para las rutinas de cifrado y descrifrado en AES de la contraseña del usuario de la base de datos y otra clase para todas las rutinas restantes: extraer texto PDF, extraer metadatos PDF, insertar registros en base de datos ODBC, obtener lista de orígenes de datos y leer y escribir valores de configuración en fichero .config. Para agregar una nueva clase al proyecto pulsaremos en el menú "Proyecto" - "Agregar clase":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Seleccionaremos "Clase" y escribiremos el nombre del fichero de la clase, por ejemplo "cifrarAES.cs", pulsaremos "Agregar":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Introduciremos el siguiente código Visual C# .Net para la clase "cifrarAES.cs" (cifrarAES):
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;  

namespace AjpdSoftIndexarTextoFicherosPDF
{
    class cifrarAES
    {
        public string cifrarTextoAES (string textoCifrar, string palabraPaso, 
            string valorRGBSalt, string algoritmoEncriptacionHASH, 
            int iteraciones, string vectorInicial, int tamanoClave)
        {
            try
            {
                byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(vectorInicial);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(valorRGBSalt);
                byte[] plainTextBytes = Encoding.UTF8.GetBytes(textoCifrar);

                PasswordDeriveBytes password = 
                    new PasswordDeriveBytes(palabraPaso, saltValueBytes, 
                        algoritmoEncriptacionHASH, iteraciones);

                byte[] keyBytes = password.GetBytes(tamanoClave / 8);

                RijndaelManaged symmetricKey = new RijndaelManaged();

                symmetricKey.Mode = CipherMode.CBC;

                ICryptoTransform encryptor = 
                    symmetricKey.CreateEncryptor(keyBytes, InitialVectorBytes);

                MemoryStream memoryStream = new MemoryStream();

                CryptoStream cryptoStream = 
                    new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);

                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);

                cryptoStream.FlushFinalBlock();

                byte[] cipherTextBytes = memoryStream.ToArray();

                memoryStream.Close();
                cryptoStream.Close();

                string textoCifradoFinal = Convert.ToBase64String(cipherTextBytes);

                return textoCifradoFinal;
            }
            catch
            {                
                return null;
            }
        }


        public string descifrarTextoAES (string textoCifrado, string palabraPaso, 
            string valorRGBSalt, string algoritmoEncriptacionHASH, 
            int iteraciones, string vectorInicial, int tamanoClave)
        {
            try
            {
                byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(vectorInicial);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(valorRGBSalt);

                byte[] cipherTextBytes = Convert.FromBase64String(textoCifrado);

                PasswordDeriveBytes password = 
                    new PasswordDeriveBytes(palabraPaso, saltValueBytes, 
                        algoritmoEncriptacionHASH, iteraciones);

                byte[] keyBytes = password.GetBytes(tamanoClave / 8);

                RijndaelManaged symmetricKey = new RijndaelManaged();

                symmetricKey.Mode = CipherMode.CBC;

                ICryptoTransform decryptor = 
                    symmetricKey.CreateDecryptor(keyBytes, InitialVectorBytes);

                MemoryStream memoryStream = new MemoryStream(cipherTextBytes);

                CryptoStream cryptoStream = 
                    new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);

                byte[] plainTextBytes = new byte[cipherTextBytes.Length];

                int decryptedByteCount = 
                    cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

                memoryStream.Close();
                cryptoStream.Close();

                string textoDescifradoFinal = 
                    Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);

                return textoDescifradoFinal;
            }
            catch
            {
                return null;
            }
        }
    }
}
De la misma forma agregaremos una segunda clase que llamaremos "Utilidades.cs":
Indexar texto fichero PDF con C# C Sharp y iTextSharp
Introduciremos el siguiente código Visual C# .Net para la clase "Utilidades.cs" (Utilidades):
using System;
using System.Configuration;
using System.Windows.Forms;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using System.Data.Odbc;
using System.Data;

namespace AjpdSoftIndexarTextoFicherosPDF
{
    class Utilidades
    {

        //para tipo de DNS (ODBC)
        public enum DataSourceType { System, User }

        //para la conexión con la BD ODBC 
        //para añadir el texto indexado de los PDF
        public OdbcConnection conexionBDODBC = new OdbcConnection();


        //leer valor del parámetro de configuración en el fichero .config
        public string leerValorConfiguracion (string clave)
        {
            try
            {
                string resultado = 
                    ConfigurationManager.AppSettings[clave].ToString();
                return resultado;
            }
            catch
            {
                return "";
            } 
        }

        //escribir valor de parámetro de configuración en fichero .config
        public void guardarValorConfiguracion(string clave, string valor)
        {
            try
            {
                //La línea siguiente no funcionará bien en tiempo de diseño
                //pues VC# usa el fichero xxx.vshost.config en la depuración
                //Configuration config = 
                //    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                //sí pues la cambiamos por:
                Configuration ficheroConfXML = 
                    ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);

                //eliminamos la clave actual (si existe), si no la eliminamos
                //los valores se irán acumulando separados por coma
                ficheroConfXML.AppSettings.Settings.Remove(clave);

                //asignamos el valor en la clave indicada
                ficheroConfXML.AppSettings.Settings.Add(clave, valor);

                //guardamos los cambios definitivamente en el fichero de configuración
                ficheroConfXML.Save(ConfigurationSaveMode.Modified);
            }
            catch
            {
               /* MessageBox.Show("Error al guardar valor de configuración: " +
                    System.Environment.NewLine + System.Environment.NewLine +
                    ex.GetType().ToString() + System.Environment.NewLine +
                    ex.Message, "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);*/
            } 
        }

        //obtiene los metadatos del fichero PDF indicado
        public string obtenerMetaDatosFicheroPDF(string ficheroPDFIndexar)
        {
            string mMetadatos = "";            
            try
            {
                PdfReader ficheroPDF = new PdfReader(ficheroPDFIndexar);
                Dictionary metadatosPDF = ficheroPDF.Info;
                foreach (KeyValuePair clavesMetadatosPDF in metadatosPDF)
                {
                    if (mMetadatos != "")
                    {
                        mMetadatos = mMetadatos + Environment.NewLine +
                            (clavesMetadatosPDF.Key + " ===> " + clavesMetadatosPDF.Value);
                    }
                    else
                    {
                        mMetadatos = (clavesMetadatosPDF.Key + " ===> " +
                            clavesMetadatosPDF.Value);
                    }
                }
                return mMetadatos;
            }
            catch
            {
                return null;
            }
        }

        //obtiene el texto del fichero PDF indicado
        public string obtenerTextoFicheroPDF(string ficheroPDF)
        {
            StringBuilder textoPDFIndexado = new StringBuilder();
            try
            {
                if (File.Exists(ficheroPDF))
                {
                    PdfReader pdfReader = new PdfReader(ficheroPDF);

                    for (int page = 1; page <= pdfReader.NumberOfPages; page++)
                    {
                        ITextExtractionStrategy strategy =
                            new SimpleTextExtractionStrategy();
                        string currentText =
                            PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);

                        currentText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(
                            Encoding.Default, Encoding.UTF8,
                            Encoding.Default.GetBytes(currentText)));
                        textoPDFIndexado.Append(currentText);
                        pdfReader.Close();
                    }
                }
                return textoPDFIndexado.ToString();
            }
            catch
            {
                return null;
            }
        }


        //obtiene todos los data sources (orígenes de datos) del sistema
        public System.Collections.SortedList obtenerDataSourcesSistema()
        {
            System.Collections.SortedList listaODBC = new System.Collections.SortedList();

            Microsoft.Win32.RegistryKey reg = 
                (Microsoft.Win32.Registry.LocalMachine).OpenSubKey("Software");
            if (reg != null)
            {
                reg = reg.OpenSubKey("ODBC");
                if (reg != null)
                {
                    reg = reg.OpenSubKey("ODBC.INI");
                    if (reg != null)
                    {
                        reg = reg.OpenSubKey("ODBC Data Sources");
                        if (reg != null)
                        {
                            // Obtener todas las entradas DSN definidas en DSN_LOC_IN_REGISTRY.
                            foreach (string sName in reg.GetValueNames())
                            {
                                listaODBC.Add(sName, DataSourceType.System);
                            }
                        }
                        try
                        {
                            reg.Close();
                        }
                        catch { /* ignorar un posible error */ }
                    }
                }
            }

            return listaODBC;
        }

        //obtiene todos los data sources (orígenes de datos) del usuario
        public SortedList obtenerDataSourcesUsuario()
        {
            SortedList listaODBC = new SortedList();

            Microsoft.Win32.RegistryKey reg =
                (Microsoft.Win32.Registry.CurrentUser).OpenSubKey("Software");
            if (reg != null)
            {
                reg = reg.OpenSubKey("ODBC");
                if (reg != null)
                {
                    reg = reg.OpenSubKey("ODBC.INI");
                    if (reg != null)
                    {
                        reg = reg.OpenSubKey("ODBC Data Sources");
                        if (reg != null)
                        {
                            // Obtener todas las entradas DSN definidas en DSN_LOC_IN_REGISTRY.
                            foreach (string sName in reg.GetValueNames())
                            {
                                listaODBC.Add(sName, DataSourceType.User);
                            }
                        }
                        try
                        {
                            reg.Close();
                        }
                        catch { /* ignorar un posible error */ }
                    }
                }
            }

            return listaODBC;
        }

        public bool existeRegistro(string ficheroPDF, 
            string campoFicheroPDF, string nombreTabla)
        {
            try
            {
                OdbcCommand comandoSQL = conexionBDODBC.CreateCommand();
                comandoSQL.CommandText = "select count(*) from " + 
                    nombreTabla + " where " + campoFicheroPDF + " = ?";

                OdbcParameter parametroSQL = new OdbcParameter();
                parametroSQL.DbType = System.Data.DbType.String;
                parametroSQL.Value = ficheroPDF;
                comandoSQL.Parameters.Add(parametroSQL);

                OdbcDataReader resultadoSQL = 
                    comandoSQL.ExecuteReader(CommandBehavior.CloseConnection);
                resultadoSQL.Read();
                Int32 numero = resultadoSQL.GetInt32(0);
                //resultadoSQL.Close(); 
                return numero > 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error de base de datos: " +
                      System.Environment.NewLine + System.Environment.NewLine +
                      ex.GetType().ToString() + System.Environment.NewLine +
                      ex.Message, "Error al crear PDF",
                      MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }          
        }



        //Insertar registro en base de datos ODBC con los datos del PDF indexado
        public void insertarRegistroBD (string ficheroPDF, string textoPDF, 
            string metadatosPDF, string campoFichero, string campoTexto, 
            string campoMetaDatos, string nombreTabla, string campoFecha, 
            bool reemplazar)
        {
            try
            {
                bool insertar = true;

                if (reemplazar)
                {
                    insertar = !existeRegistro(ficheroPDF, campoFichero, nombreTabla);
                }

                //actualizar registro ya existente
                if (!insertar)
                {
                    OdbcCommand comandoSQL = conexionBDODBC.CreateCommand();
                    comandoSQL.CommandText = "update " + nombreTabla + " set " +
                        campoTexto + " = ?, " +
                        campoMetaDatos + " = ?, " +
                        campoFecha + " = ?" +
                        " where " + campoFichero + " = ?";

                    OdbcParameter parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = textoPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = metadatosPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.Date;
                    parametroSQL.Value = DateTime.Now;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = ficheroPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    comandoSQL.ExecuteNonQuery();
                }

                //insertar nuevo registro
                if (insertar)
                {
                    OdbcCommand comandoSQL = conexionBDODBC.CreateCommand();
                    comandoSQL.CommandText = "insert into " + nombreTabla +
                        " (" + campoFichero + "," + campoTexto +
                        "," + campoMetaDatos + ", " + campoFecha +
                        ") values (?, ?, ?, ?)";

                    OdbcParameter parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = ficheroPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = textoPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = metadatosPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.Date;
                    parametroSQL.Value = DateTime.Now;
                    comandoSQL.Parameters.Add(parametroSQL);

                    comandoSQL.ExecuteNonQuery();

                    /*  
                    //Segundo método de inserción SQL con parámetros                 
                    OdbcCommand cmd = new OdbcCommand();
                    cmd.Connection = conexionBDODBC;
                    cmd.CommandText = "INSERT INTO " + nombreTabla + " (" +
                        campoFichero + ", " + campoTexto + ", " +
                        campoMetaDatos + ", " + campoFecha +
                        " ) VALUES (@ficheroPDF, @textoPDF, @metadatosPDF, @fecha);";
                    cmd.Parameters.AddWithValue("@ficheroPDF", ficheroPDF);
                    cmd.Parameters.AddWithValue("@textoPDF", textoPDF);
                    cmd.Parameters.AddWithValue("@metadatosPDF", metadatosPDF);
                    cmd.Parameters.AddWithValue("@fecha", DateTime.Now);
                    cmd.ExecuteNonQuery();
                    */
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error de base de datos: " +
                      System.Environment.NewLine + System.Environment.NewLine +
                      ex.GetType().ToString() + System.Environment.NewLine +
                      ex.Message, "Error al crear PDF",
                      MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}


A continuación mostramos el código fuente Visual C# .Net de cada botón y cada evento del formulario principal (formIndexarPDF.cs). Todo el código y la aplicación completa están disponibles gratuitamente en: AjpdSoft Indexar Texto PDF C# iTextSharp:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Data.Odbc;


namespace AjpdSoftIndexarTextoFicherosPDF
{
    public partial class formIndexarPDF : Form
    {

        Utilidades util = new Utilidades();        
        
        public formIndexarPDF()
        {
            InitializeComponent();
        }

        private void btInsertarDocPDFIndexar_Click(object sender, EventArgs e)
        {
            dlAbrir.CheckFileExists = true;
            dlAbrir.CheckPathExists = true;
            dlAbrir.Multiselect = true;
            dlAbrir.DefaultExt = "pdf";
            dlAbrir.FileName = "";
            dlAbrir.Filter = "Archivos PDF (*.pdf)|*.pdf|Todos los archivos (*.*)|*.*";
            dlAbrir.Title = "Seleccionar fichero PDF a dividir y separar páginas";
            if (dlAbrir.ShowDialog() == DialogResult.OK)
            {
                lsPDFIndexar.Items.AddRange(dlAbrir.FileNames);
                for (int i = 0; i < lsPDFIndexar.Items.Count; ++i)
                    lsPDFIndexar.SetItemChecked(i, true);
            }         
        }

        private void btIndexarPDF_Click(object sender, EventArgs e)
        {
            if (lsPDFIndexar.CheckedItems.Count != 0)
            {
                string textoIndexadoPDFTodos = "";
                string textoIndexadoPDFActual = "";
                string ficheroPDFIndexar = "";
                string mMetadatos = "";
                int numElementos = lsPDFIndexar.CheckedItems.Count;

                this.Cursor = Cursors.WaitCursor;
                bp.Minimum = 0;
                bp.Maximum = numElementos - 1;
                bp.Value = 0;

                for (int i = 0; i <= lsPDFIndexar.CheckedItems.Count - 1; i++)
                {
                    ficheroPDFIndexar = lsPDFIndexar.CheckedItems[i].ToString();
                    bp.Value = i;
                    lInfo.Text = Convert.ToString(i + 1) +
                        "/" + Convert.ToString(numElementos) +
                        " [" + Path.GetFileName(ficheroPDFIndexar) + "]";
                    Application.DoEvents();
                    //obtener metadatos del fichero PDF
                    mMetadatos = util.obtenerMetaDatosFicheroPDF(ficheroPDFIndexar);
                    //obtener el texto del PDF
                    textoIndexadoPDFActual = util.obtenerTextoFicheroPDF(ficheroPDFIndexar);

                    if (textoIndexadoPDFTodos != "")
                    {
                        textoIndexadoPDFTodos = textoIndexadoPDFTodos +
                            Environment.NewLine + Environment.NewLine +
                            "==================================" +
                            Environment.NewLine + Environment.NewLine +
                            "Fichero: " + ficheroPDFIndexar + Environment.NewLine +
                            mMetadatos + Environment.NewLine + textoIndexadoPDFActual;
                    }
                    else
                    {
                        textoIndexadoPDFTodos =
                            "Fichero: " + ficheroPDFIndexar + Environment.NewLine +
                            mMetadatos + Environment.NewLine + textoIndexadoPDFActual;
                    }
                }
                txtResultadoIndexacionPDF.Text = textoIndexadoPDFTodos;
                this.Cursor = Cursors.Default;
                lInfo.Text = "Proceso de indexación de PDF finalizado";
                bp.Value = 0;
                MessageBox.Show("Proceso de indexación de PDF finalizado correctamente.",
                    "Fin proceso", MessageBoxButtons.OK, MessageBoxIcon.Information); 
            }
            else
            {
                btInsertarDocPDFIndexar.Focus();
                MessageBox.Show("Debe chequear los ficheros PDF a indexar a pantalla.", 
                    "Seleccionar PDF", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void btSelTodos_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < lsPDFIndexar.Items.Count; i++)
            {
                lsPDFIndexar.SetItemChecked(i, true);
            }
        }

        private void btNinguno_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < lsPDFIndexar.Items.Count; i++)
            {
                lsPDFIndexar.SetItemChecked(i, false);
            }
        }

        private void btInvertir_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < lsPDFIndexar.Items.Count; i++)
            {
                lsPDFIndexar.SetItemChecked(i, ! lsPDFIndexar.GetItemChecked(i));
            }
        }

        private void bConectar_Click(object sender, EventArgs e)
        {
            if (txtTabla.Text != "")  
            {
                try
                {
                    if (lsODBC.Text != "")
                    {
                        util.conexionBDODBC = new OdbcConnection("dsn=" + lsODBC.Text +
                            ";UID=" + txtUsuario.Text + ";PWD=" + txtContrasena.Text + ";");
                    }
                    else
                    {
                        if (txtPuerto.Text != "")
                        {
                            util.conexionBDODBC = new OdbcConnection("DRIVER={" + lsMotor.Text +
                                "};SERVER=" + txtServidor.Text + "; PORT=" + txtPuerto.Text +
                                ";UID=" + txtUsuario.Text +
                                ";PWD=" + txtContrasena.Text + ";" +
                                ";DATABASE=" + txtBD.Text + ";");
                        }
                        else
                        {
                            util.conexionBDODBC = new OdbcConnection("DRIVER={" + lsMotor.Text +
                                "};SERVER=" + txtServidor.Text + ";UID=" + txtUsuario.Text +
                                ";PWD=" + txtContrasena.Text + ";" +
                                ";DATABASE=" + txtBD.Text + ";");
                        }
                    }

                    util.conexionBDODBC.Open();

                    if (util.conexionBDODBC.State == ConnectionState.Open)
                    {
                        bDesconectar.Enabled = true;
                        bConectar.Enabled = false;

                        OdbcCommand comandoSQL;
                        string consultaSQL;

                        consultaSQL = "Select count(*) from " + txtTabla.Text;
                        try
                        {
                            comandoSQL = new OdbcCommand(consultaSQL, util.conexionBDODBC);
                            int numeroRegistros = Convert.ToInt32(comandoSQL.ExecuteScalar());
                            MessageBox.Show("La tabla " + txtTabla.Text + " existe con " +
                                Convert.ToString(numeroRegistros) + " registros.", "Conexión BD",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                            beConectadoBD.Text = "Conectado a BD";
                            bDesconectar.Enabled = true;
                            bConectar.Enabled = false;
                        }
                        catch (Exception ex)
                        {
                            util.conexionBDODBC.Close();
                            bDesconectar.Enabled = false;
                            bConectar.Enabled = true;
                            MessageBox.Show("Error al ejecutar SQL: " +
                                System.Environment.NewLine + System.Environment.NewLine +
                                ex.GetType().ToString() + System.Environment.NewLine +
                                ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                    else
                    {
                        beConectadoBD.Text = "No conectado a BD";
                        bDesconectar.Enabled = false;
                        bConectar.Enabled = true;
                        MessageBox.Show("No conectado a la base de datos.", "Conexión BD",
                            MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                }
                catch (Exception error)
                {
                    bDesconectar.Enabled = false;
                    bConectar.Enabled = true;
                    beConectadoBD.Text = "No conectado a BD";
                    util.conexionBDODBC.Close();
                    MessageBox.Show("Error de base de datos: " +
                        System.Environment.NewLine + System.Environment.NewLine +
                        error.GetType().ToString() + System.Environment.NewLine +
                        error.Message, "Error al crear PDF",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                
            }            
            else
            {
                MessageBox.Show("Debe indicar el nombre de la tabla de " +
                    "la BD donde se crearán los registros " +
                    "con el indexado del los PDF.", "Tabla",
                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                txtTabla.Focus();
            }            
        }

        private void btListaODBC_Click(object sender, EventArgs e)
        {
            SortedList listaODBC = new System.Collections.SortedList();
            lsODBC.Items.Clear();
            listaODBC = util.obtenerDataSourcesSistema();
            foreach (DictionaryEntry key in listaODBC)
            {
                lsODBC.Items.Add(key.Key.ToString());
            }
            listaODBC = util.obtenerDataSourcesUsuario();
            foreach (DictionaryEntry key in listaODBC)
            {
                lsODBC.Items.Add(key.Key.ToString());
            }
        }

        private void btGuardarTextoFichero_Click(object sender, EventArgs e)
        {
            dlGuardar.Title = "Selección de carpeta y fichero de " +
                "texto donde se guardará la indexación";
            dlGuardar.Filter = "Texto (*.txt)|*.txt|Todos los ficheros (*.*)|*.*";
            dlGuardar.DefaultExt = "txt";
            dlGuardar.FilterIndex = 1;
            dlGuardar.CheckFileExists = false;
            dlGuardar.OverwritePrompt = true;
            if (dlGuardar.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    StreamWriter ficheroTexto = new StreamWriter(dlGuardar.FileName,
                        false, System.Text.Encoding.Default);
                    ficheroTexto.Write(txtResultadoIndexacionPDF.Text);
                    ficheroTexto.Flush();
                    ficheroTexto.Close();
                    MessageBox.Show("Fichero de texto guardado correctamente.", 
                        "Fichero guardado",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error al guardar fichero de texto: " +
                        System.Environment.NewLine + System.Environment.NewLine +
                        ex.GetType().ToString() + System.Environment.NewLine +
                        ex.Message, "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void bDesconectar_Click(object sender, EventArgs e)
        {
            try
            {
                util.conexionBDODBC.Close();
                bDesconectar.Enabled = false;                
                bConectar.Enabled = true;
                beConectadoBD.Text = "No conectado a BD";
                bConectar.Focus();
            }
            catch (Exception error)
            {
                bDesconectar.Enabled = false;
                bConectar.Enabled = true;
                MessageBox.Show("Error de base de datos: " +
                    System.Environment.NewLine + System.Environment.NewLine +
                    error.GetType().ToString() + System.Environment.NewLine +
                    error.Message, "Error al crear PDF",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btIndexarPDFBD_Click(object sender, EventArgs e)
        {
            if (util.conexionBDODBC.State == ConnectionState.Open)
            {
                if (lsPDFIndexar.CheckedItems.Count != 0)
                {
                    string textoIndexadoPDF = "";
                    string ficheroPDFIndexar = "";
                    string mMetadatos = "";
                    int numElementos = lsPDFIndexar.CheckedItems.Count;

                    this.Cursor = Cursors.WaitCursor;
                    bp.Minimum = 0;
                    bp.Maximum = numElementos - 1;
                    bp.Value = 0;

                    for (int i = 0; i <= numElementos - 1; i++)
                    {
                        bp.Value = i;
                        ficheroPDFIndexar = lsPDFIndexar.CheckedItems[i].ToString();
                        lInfo.Text = Convert.ToString(i + 1) +
                            "/" + Convert.ToString(numElementos) + 
                            " [" + Path.GetFileName (ficheroPDFIndexar) + "]";
                        Application.DoEvents();
                        //Obtener metadatos del fichero PDF
                        mMetadatos = util.obtenerMetaDatosFicheroPDF(ficheroPDFIndexar);
                        //obtener texto indexado del PDF
                        textoIndexadoPDF = util.obtenerTextoFicheroPDF(ficheroPDFIndexar);
                        util.insertarRegistroBD(ficheroPDFIndexar, textoIndexadoPDF,
                              mMetadatos, txtCampoFicheroPDF.Text, 
                              txtCampoTextoPDF.Text, txtCampoMetadatosPDF.Text,
                              txtTabla.Text, txtCampoFecha.Text, opBDIndexarReemplazar.Checked);                            
                    }
                    this.Cursor = Cursors.Default;
                    lInfo.Text = "Proceso de indexación de PDF finalizado";
                    bp.Value = 0;
                    util.conexionBDODBC.Close();
                    bConectar.Enabled = true;
                    bDesconectar.Enabled = false;
                    beConectadoBD.Text = "No conectado a BD";
                    MessageBox.Show("Proceso de indexación de PDF finalizado correctamente.",
                        "Fin proceso", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    btInsertarDocPDFIndexar.Focus();
                    MessageBox.Show("Debe chequear los ficheros PDF a indexar a base de datos.",
                        "Seleccionar PDF", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show("Debe estar conectado a la base de datos para " +
                    "realizar la indexación de los ficheros PDF seleccionados.", 
                    "Error al crear PDF", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }


        private void formIndexarPDF_FormClosed(object sender, FormClosedEventArgs e)
        {
            Utilidades proUtilidades = new Utilidades();
            cifrarAES cifradoAES = new cifrarAES();
 
            proUtilidades.guardarValorConfiguracion("BD.ODBC", lsODBC.Text);    
            proUtilidades.guardarValorConfiguracion("BD.Motor", lsMotor.Text);
            proUtilidades.guardarValorConfiguracion("BD.Servidor", txtServidor.Text);
            proUtilidades.guardarValorConfiguracion("BD.Usuario", txtUsuario.Text);
            proUtilidades.guardarValorConfiguracion("BD.Contraseña", 
                cifradoAES.cifrarTextoAES (txtContrasena.Text,
                "AjpdSoft_Frase_Encriptado", "AjpdSoft_Frase_Encriptado", 
                "MD5", 22, "1234567891234567", 128));
            proUtilidades.guardarValorConfiguracion("BD.Base_Datos", txtBD.Text);
            proUtilidades.guardarValorConfiguracion("BD.Puerto", txtPuerto.Text);
            proUtilidades.guardarValorConfiguracion("BD.Tabla", txtTabla.Text);
            proUtilidades.guardarValorConfiguracion("BD.Campo_Texto_Indexado", 
                txtCampoTextoPDF.Text);
            proUtilidades.guardarValorConfiguracion("BD.Campo_Fecha", 
                txtCampoFecha.Text);    
            proUtilidades.guardarValorConfiguracion("BD.Campo_Metadatos", 
                txtCampoMetadatosPDF.Text);
            proUtilidades.guardarValorConfiguracion("BD.Campo_Fichero_PDF", 
                txtCampoFicheroPDF.Text);
        }

        private void btSQL_Click(object sender, EventArgs e)
        {
            formSQL frmSQL = new formSQL();
            frmSQL.ShowDialog();
        }

        private void formIndexarPDF_Load(object sender, EventArgs e)
        {                    
            Utilidades proUtilidades = new Utilidades();
            cifrarAES cifradoAES = new cifrarAES();

            lsODBC.Text = 
                proUtilidades.leerValorConfiguracion("BD.ODBC");
            lsMotor.Text = 
                proUtilidades.leerValorConfiguracion("BD.Motor");
            txtServidor.Text = 
                proUtilidades.leerValorConfiguracion("BD.Servidor");
            txtUsuario.Text = 
                proUtilidades.leerValorConfiguracion("BD.Usuario");
            txtContrasena.Text =
                cifradoAES.descifrarTextoAES(
                  proUtilidades.leerValorConfiguracion("BD.Contraseña"),
                  "AjpdSoft_Frase_Encriptado", "AjpdSoft_Frase_Encriptado", 
                  "MD5", 22, "1234567891234567", 128);
            txtBD.Text = 
                proUtilidades.leerValorConfiguracion("BD.Base_Datos");
            txtPuerto.Text = 
                proUtilidades.leerValorConfiguracion("BD.Puerto");
            txtTabla.Text= 
                proUtilidades.leerValorConfiguracion("BD.Tabla");
            txtCampoTextoPDF.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Texto_Indexado");            
            txtCampoFecha.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Fecha");
            txtCampoMetadatosPDF.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Metadatos");
            txtCampoFicheroPDF.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Fichero_PDF");
        }

        private void toolStripStatusLabel1_Click_1(object sender, EventArgs e)
        {
            //abrir navegador por defecto y acceder a la URL www.ajpdsoft.com
            System.Diagnostics.Process.Start("http://www.ajpdsoft.com");
        }
    }
}
El formulario "formSQL.cs" contendrá el siguiente código Visual C# .Net:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AjpdSoftIndexarTextoFicherosPDF
{
    public partial class formSQL : Form
    {
        public formSQL()
        {
            InitializeComponent();
        }

        private void formSQL_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.Dispose();
        }

        private void btCerrar_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btCopiarPortapapeles_Click(object sender, EventArgs e)
        {
            try
            {
                Clipboard.SetDataObject(txtSQL.SelectedText, true);
                MessageBox.Show("Texto copiado al portapapeles de Windows.",
                    "Copiado", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception err)
            {
                MessageBox.Show("Error al copiar texto al portapapeles: " +
                    Environment.NewLine + err.Message, "Error al copiar", 
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}

AjpdSoft Indexar Texto PDF C# iTextSharp

AjpdSoft Indexar Texto PDF C# iTextSharp permite extraer el texto y los metadatos de los ficheros PDF seleccionados y guardarlo en la tabla de una base de datos.
AjpdSoft Indexar Texto PDF C# iTextSharp no necesita usar ningún software de terceros, únicamente usa la librería gratuita iTextSharp.dll.
A continuación explicamos cómo funciona la aplicación AjpdSoft Indexar Texto PDF C# iTextSharp. La aplicación permite dos opciones de indexación o extracción de texto y metadatos de ficheros PDF, o bien mostrándolo en pantalla o bien guardándolo en base de datos. Para la primera opción, pulsaremos en el botón "+" para seleccionar los ficheros PDF que queramos indexar (permite selección de múltiples ficheros en la misma o diferentes carpetas):
AjpdSoft Indexar Texto PDF C# iTextSharp
Seleccionaremos los ficheros PDF a indexar:
AjpdSoft Indexar Texto PDF C# iTextSharp
Para extraer el texto y los metadatos de todos los ficheros PDF chequeados y mostrarlo en pantalla pulsaremos "Indexar PDFs a cuadro de texto":
AjpdSoft Indexar Texto PDF C# iTextSharp
La aplicación mostrará el progreso del proceso en la barra de estado, indicando el fichero PDF actual, los que va a indexar y una barra de progreso. Cuando el proceso de indexación concluya mostrará un mensaje como el siguiente "Proceso de indexación de PDF finalizado correctamente":
AjpdSoft Indexar Texto PDF C# iTextSharp
Desde el cuadro de texto podremos copiar el texto extraído de los ficheros PDF al portapapeles o bien guardarlo desde la aplicación en fichero de texto pulsando en "Guardar en fichero":
AjpdSoft Indexar Texto PDF C# iTextSharp
La segunda posibilidad que presenta la aplicación es guardar los datos extraídos de los ficheros PDF en una tabla de una base de datos ODBC. Si hemos configurado un servidor de base de datos que soporte ODBC y hemos creado la tabla correspondiente como indicamos aquí podremos configurar AjpdSoft Indexar Texto PDF C# iTextSharp para guardar los datos obtenidos en una base de datos.
Para guardar los datos indexados de los PDF en una base de datos, la aplicación AjpdSoft Indexar Texto PDF C# iTextSharp permite dos opciones de conexión:
1. Si ya tenemos un origen de datos ODBC creado en el equipo podremos seleccionarlo (o escribirlo) en "ODBC existente en el equipo", usando esta opción no tendremos que introducir ningún dato más pues todos los datos se establecen en el origen de datos, como indicamos aquí:
AjpdSoft Indexar Texto PDF C# iTextSharp
Si optamos por esta opción, como decimos, no habrá que introducir más datos para la conexión con la base de datos.
2. La segunda posibilidad es dejar en blanco el campo anterior (ODBC existente en el equipo) e introducir los datos de conexión en "Nuevo ODBC". Si elegimos esta opción tendremos la ventaja de que no hay que crear ningún origen de datos en el equipo, directamente AjpdSoft Indexar Texto PDF C# iTextSharp usará los siguientes datos para establecer la conexión:
  • Motor BD: nombre exacto del origen de datos ODBC, en el desplegable aparecen un listado de los nombres "típicos", pero pueden variar en función de las versiones instaladas de cada controlador de cada motor de base de datos. En nuestro caso usaremos "PostgreSQL ANSI".
  • Servidor BD: IP o hostname del equipo con la base de datos instalada, en nuestro caso "pcajpdsoft".
  • Usuario: nombre de usuario del motor de base de datos con permisos suficientes para insertar registros en la tabla indicada.
  • Contraseña: contraseña del usuario de la base de datos.
  • BD: nombre de la base de datos a la que nos conectaremos, en nuestro ejemplo "indexadopdf".
  • Puerto: podemos dejarlo en blanco para usar el puerto por defecto del motor de base de datos elegido o bien especificar uno si es diferente al de defecto.
AjpdSoft Indexar Texto PDF C# iTextSharp
Una vez elegido el método de conexión (ODBC existente o bien ODBC nuevo) introduciremos los datos para la tabla de la base de datos:
  • Tabla: nombre de la tabla de la base de datos donde guardaremos el texto extraído de los ficheros PDF.
  • Campo texto: nombre del campo de la tabla donde se guardará el texto obtenido del fichero PDF.
  • Campo metadatos: nombre del campo de la tabla donde se guardarán los metadatos obtenidos del fichero PDF.
  • Campo fecha: nombre del campo de la tabla donde se guardará la fecha actual, la fecha en la que se realiza la indexación.
  • Campo nombre fichero: nombre del campo de la tabla donde se guardará la ruta y el nombre del fichero PDF indexado.
AjpdSoft Indexar Texto PDF C# iTextSharp
A continuación pulsaremos en "Conectar" para comprobar la conexión a la base de datos y la existencia de la tabla indicada:
AjpdSoft Indexar Texto PDF C# iTextSharp
Si todo es correcto la aplicación AjpdSoft Indexar Texto PDF C# iTextSharp mostrará el mensaje "La tabla indexpdf" existe con xxx registros". Si hay algún error en la conexión o falta algún dato la aplicación mostrará el error:
AjpdSoft Indexar Texto PDF C# iTextSharp
Por último, una vez establecido el método de conexión y los datos de la tabla de la base de datos podremos marcar la opción "Reemplazar registros con nombre de fichero común" para que la aplicación AjpdSoft Indexar Texto PDF C# iTextSharp, antes de insertar un nuevo registro en la tabla, compruebe si ya existe usando la carpeta y el nombre del fichero PDF previamente indexado. Si existe se actualizará y si no existe se creará un nuevo registro. Si no marcamos esta opción siempre se añadirá un nuevo registro sin realizar comprobación previa de su existencia. Tras seleccionar el método de reemplazo pulsaremos en "Indexar PDFs a base de datos" para iniciar el proceso definitivo:
AjpdSoft Indexar Texto PDF C# iTextSharp
La aplicación AjpdSoft Indexar Texto PDF C# iTextSharp mostrará el progreso del proceso de indexación con una barra de progreso e indicando los ficheros indexados y los que quedan por indexar, todo ello lo mostrará en la barra de tareas:
AjpdSoft Indexar Texto PDF C# iTextSharp
Una vez finalizado el proceso podremos acceder usando cualquier software de consulta de SQL al motor de base de datos que hayamos elegido como destino de la indexación para consultar y buscar los datos de los ficheros PDF:
AjpdSoft Indexar Texto PDF C# iTextSharp

Código fuente completo de AjpdSoft Indexar Texto PDF C# iTextSharp

A continuación mostramos el enlace para descargar gratuitamente el código fuente completo de la aplicación AjpdSoft Indexar Texto PDF C# iTextSharp desarrollada con Visual C# .Net 2010 (de Microsoft Studio .Net 2010):
El listado completo del código fuente de la aplicación AjpdSoft Indexar Texto PDF C# iTextSharp:
  • Código para "cifrarAES.cs" (clase para cifrado de texto en AES):
using System;
using System.Security.Cryptography;
using System.Text;
using System.IO;  

namespace AjpdSoftIndexarTextoFicherosPDF
{
    class cifrarAES
    {
        public string cifrarTextoAES (string textoCifrar, string palabraPaso, 
            string valorRGBSalt, string algoritmoEncriptacionHASH, 
            int iteraciones, string vectorInicial, int tamanoClave)
        {
            try
            {
                byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(vectorInicial);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(valorRGBSalt);
                byte[] plainTextBytes = Encoding.UTF8.GetBytes(textoCifrar);

                PasswordDeriveBytes password = 
                    new PasswordDeriveBytes(palabraPaso, saltValueBytes, 
                        algoritmoEncriptacionHASH, iteraciones);

                byte[] keyBytes = password.GetBytes(tamanoClave / 8);

                RijndaelManaged symmetricKey = new RijndaelManaged();

                symmetricKey.Mode = CipherMode.CBC;

                ICryptoTransform encryptor = 
                    symmetricKey.CreateEncryptor(keyBytes, InitialVectorBytes);

                MemoryStream memoryStream = new MemoryStream();

                CryptoStream cryptoStream = 
                    new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);

                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);

                cryptoStream.FlushFinalBlock();

                byte[] cipherTextBytes = memoryStream.ToArray();

                memoryStream.Close();
                cryptoStream.Close();

                string textoCifradoFinal = Convert.ToBase64String(cipherTextBytes);

                return textoCifradoFinal;
            }
            catch
            {                
                return null;
            }
        }


        public string descifrarTextoAES (string textoCifrado, string palabraPaso, 
            string valorRGBSalt, string algoritmoEncriptacionHASH, 
            int iteraciones, string vectorInicial, int tamanoClave)
        {
            try
            {
                byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(vectorInicial);
                byte[] saltValueBytes = Encoding.ASCII.GetBytes(valorRGBSalt);

                byte[] cipherTextBytes = Convert.FromBase64String(textoCifrado);

                PasswordDeriveBytes password = 
                    new PasswordDeriveBytes(palabraPaso, saltValueBytes, 
                        algoritmoEncriptacionHASH, iteraciones);

                byte[] keyBytes = password.GetBytes(tamanoClave / 8);

                RijndaelManaged symmetricKey = new RijndaelManaged();

                symmetricKey.Mode = CipherMode.CBC;

                ICryptoTransform decryptor = 
                    symmetricKey.CreateDecryptor(keyBytes, InitialVectorBytes);

                MemoryStream memoryStream = new MemoryStream(cipherTextBytes);

                CryptoStream cryptoStream = 
                    new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);

                byte[] plainTextBytes = new byte[cipherTextBytes.Length];

                int decryptedByteCount = 
                    cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);

                memoryStream.Close();
                cryptoStream.Close();

                string textoDescifradoFinal = 
                    Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);

                return textoDescifradoFinal;
            }
            catch
            {
                return null;
            }
        }
    }
}
 
       
  • Código para la clase "Utilidades.cs" (acceso a base de datos, obtención de lista de ODBC, inserción de registros en BD, indexación de texto PDF, extracción de metadatos PDF, leer y guardar valores de configuración: 
 
using System;
using System.Configuration;
using System.Windows.Forms;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using iTextSharp.text.pdf.parser;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using System.Data.Odbc;
using System.Data;

namespace AjpdSoftIndexarTextoFicherosPDF
{
    class Utilidades
    {

        //para tipo de DNS (ODBC)
        public enum DataSourceType { System, User }

        //para la conexión con la BD ODBC 
        //para añadir el texto indexado de los PDF
        public OdbcConnection conexionBDODBC = new OdbcConnection();


        //leer valor del parámetro de configuración en el fichero .config
        public string leerValorConfiguracion (string clave)
        {
            try
            {
                string resultado = 
                    ConfigurationManager.AppSettings[clave].ToString();
                return resultado;
            }
            catch
            {
                return "";
            } 
        }

        //escribir valor de parámetro de configuración en fichero .config
        public void guardarValorConfiguracion(string clave, string valor)
        {
            try
            {
                //La línea siguiente no funcionará bien en tiempo de diseño
                //pues VC# usa el fichero xxx.vshost.config en la depuración
                //Configuration config = 
                //    ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                //sí pues la cambiamos por:
                Configuration ficheroConfXML = 
                    ConfigurationManager.OpenExeConfiguration(Application.ExecutablePath);

                //eliminamos la clave actual (si existe), si no la eliminamos
                //los valores se irán acumulando separados por coma
                ficheroConfXML.AppSettings.Settings.Remove(clave);

                //asignamos el valor en la clave indicada
                ficheroConfXML.AppSettings.Settings.Add(clave, valor);

                //guardamos los cambios definitivamente en el fichero de configuración
                ficheroConfXML.Save(ConfigurationSaveMode.Modified);
            }
            catch
            {
               /* MessageBox.Show("Error al guardar valor de configuración: " +
                    System.Environment.NewLine + System.Environment.NewLine +
                    ex.GetType().ToString() + System.Environment.NewLine +
                    ex.Message, "Error",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);*/
            } 
        }

        //obtiene los metadatos del fichero PDF indicado
        public string obtenerMetaDatosFicheroPDF(string ficheroPDFIndexar)
        {
            string mMetadatos = "";            
            try
            {
                PdfReader ficheroPDF = new PdfReader(ficheroPDFIndexar);
                Dictionary metadatosPDF = ficheroPDF.Info;
                foreach (KeyValuePair clavesMetadatosPDF in metadatosPDF)
                {
                    if (mMetadatos != "")
                    {
                        mMetadatos = mMetadatos + Environment.NewLine +
                            (clavesMetadatosPDF.Key + " ===> " + clavesMetadatosPDF.Value);
                    }
                    else
                    {
                        mMetadatos = (clavesMetadatosPDF.Key + " ===> " +
                            clavesMetadatosPDF.Value);
                    }
                }
                return mMetadatos;
            }
            catch
            {
                return null;
            }
        }

        //obtiene el texto del fichero PDF indicado
        public string obtenerTextoFicheroPDF(string ficheroPDF)
        {
            StringBuilder textoPDFIndexado = new StringBuilder();
            try
            {
                if (File.Exists(ficheroPDF))
                {
                    PdfReader pdfReader = new PdfReader(ficheroPDF);

                    for (int page = 1; page <= pdfReader.NumberOfPages; page++)
                    {
                        ITextExtractionStrategy strategy =
                            new SimpleTextExtractionStrategy();
                        string currentText =
                            PdfTextExtractor.GetTextFromPage(pdfReader, page, strategy);

                        currentText = Encoding.UTF8.GetString(ASCIIEncoding.Convert(
                            Encoding.Default, Encoding.UTF8,
                            Encoding.Default.GetBytes(currentText)));
                        textoPDFIndexado.Append(currentText);
                        pdfReader.Close();
                    }
                }
                return textoPDFIndexado.ToString();
            }
            catch
            {
                return null;
            }
        }


        //obtiene todos los data sources (orígenes de datos) del sistema
        public System.Collections.SortedList obtenerDataSourcesSistema()
        {
            System.Collections.SortedList listaODBC = new System.Collections.SortedList();

            Microsoft.Win32.RegistryKey reg = 
                (Microsoft.Win32.Registry.LocalMachine).OpenSubKey("Software");
            if (reg != null)
            {
                reg = reg.OpenSubKey("ODBC");
                if (reg != null)
                {
                    reg = reg.OpenSubKey("ODBC.INI");
                    if (reg != null)
                    {
                        reg = reg.OpenSubKey("ODBC Data Sources");
                        if (reg != null)
                        {
                            // Obtener todas las entradas DSN definidas en DSN_LOC_IN_REGISTRY.
                            foreach (string sName in reg.GetValueNames())
                            {
                                listaODBC.Add(sName, DataSourceType.System);
                            }
                        }
                        try
                        {
                            reg.Close();
                        }
                        catch { /* ignorar un posible error */ }
                    }
                }
            }

            return listaODBC;
        }

        //obtiene todos los data sources (orígenes de datos) del usuario
        public SortedList obtenerDataSourcesUsuario()
        {
            SortedList listaODBC = new SortedList();

            Microsoft.Win32.RegistryKey reg =
                (Microsoft.Win32.Registry.CurrentUser).OpenSubKey("Software");
            if (reg != null)
            {
                reg = reg.OpenSubKey("ODBC");
                if (reg != null)
                {
                    reg = reg.OpenSubKey("ODBC.INI");
                    if (reg != null)
                    {
                        reg = reg.OpenSubKey("ODBC Data Sources");
                        if (reg != null)
                        {
                            // Obtener todas las entradas DSN definidas en DSN_LOC_IN_REGISTRY.
                            foreach (string sName in reg.GetValueNames())
                            {
                                listaODBC.Add(sName, DataSourceType.User);
                            }
                        }
                        try
                        {
                            reg.Close();
                        }
                        catch { /* ignorar un posible error */ }
                    }
                }
            }

            return listaODBC;
        }

        public bool existeRegistro(string ficheroPDF, 
            string campoFicheroPDF, string nombreTabla)
        {
            try
            {
                OdbcCommand comandoSQL = conexionBDODBC.CreateCommand();
                comandoSQL.CommandText = "select count(*) from " + 
                    nombreTabla + " where " + campoFicheroPDF + " = ?";

                OdbcParameter parametroSQL = new OdbcParameter();
                parametroSQL.DbType = System.Data.DbType.String;
                parametroSQL.Value = ficheroPDF;
                comandoSQL.Parameters.Add(parametroSQL);

                OdbcDataReader resultadoSQL = 
                    comandoSQL.ExecuteReader(CommandBehavior.CloseConnection);
                resultadoSQL.Read();
                Int32 numero = resultadoSQL.GetInt32(0);
                //resultadoSQL.Close(); 
                return numero > 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error de base de datos: " +
                      System.Environment.NewLine + System.Environment.NewLine +
                      ex.GetType().ToString() + System.Environment.NewLine +
                      ex.Message, "Error al crear PDF",
                      MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }          
        }



        //Insertar registro en base de datos ODBC con los datos del PDF indexado
        public void insertarRegistroBD (string ficheroPDF, string textoPDF, 
            string metadatosPDF, string campoFichero, string campoTexto, 
            string campoMetaDatos, string nombreTabla, string campoFecha, 
            bool reemplazar)
        {
            try
            {
                bool insertar = true;

                if (reemplazar)
                {
                    insertar = !existeRegistro(ficheroPDF, campoFichero, nombreTabla);
                }

                //actualizar registro ya existente
                if (!insertar)
                {
                    OdbcCommand comandoSQL = conexionBDODBC.CreateCommand();
                    comandoSQL.CommandText = "update " + nombreTabla + " set " +
                        campoTexto + " = ?, " +
                        campoMetaDatos + " = ?, " +
                        campoFecha + " = ?" +
                        " where " + campoFichero + " = ?";

                    OdbcParameter parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = textoPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = metadatosPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.Date;
                    parametroSQL.Value = DateTime.Now;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = ficheroPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    comandoSQL.ExecuteNonQuery();
                }

                //insertar nuevo registro
                if (insertar)
                {
                    OdbcCommand comandoSQL = conexionBDODBC.CreateCommand();
                    comandoSQL.CommandText = "insert into " + nombreTabla +
                        " (" + campoFichero + "," + campoTexto +
                        "," + campoMetaDatos + ", " + campoFecha +
                        ") values (?, ?, ?, ?)";

                    OdbcParameter parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = ficheroPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = textoPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.String;
                    parametroSQL.Value = metadatosPDF;
                    comandoSQL.Parameters.Add(parametroSQL);

                    parametroSQL = new OdbcParameter();
                    parametroSQL.DbType = System.Data.DbType.Date;
                    parametroSQL.Value = DateTime.Now;
                    comandoSQL.Parameters.Add(parametroSQL);

                    comandoSQL.ExecuteNonQuery();

                    /*  
                    //Segundo método de inserción SQL con parámetros                 
                    OdbcCommand cmd = new OdbcCommand();
                    cmd.Connection = conexionBDODBC;
                    cmd.CommandText = "INSERT INTO " + nombreTabla + " (" +
                        campoFichero + ", " + campoTexto + ", " +
                        campoMetaDatos + ", " + campoFecha +
                        " ) VALUES (@ficheroPDF, @textoPDF, @metadatosPDF, @fecha);";
                    cmd.Parameters.AddWithValue("@ficheroPDF", ficheroPDF);
                    cmd.Parameters.AddWithValue("@textoPDF", textoPDF);
                    cmd.Parameters.AddWithValue("@metadatosPDF", metadatosPDF);
                    cmd.Parameters.AddWithValue("@fecha", DateTime.Now);
                    cmd.ExecuteNonQuery();
                    */
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error de base de datos: " +
                      System.Environment.NewLine + System.Environment.NewLine +
                      ex.GetType().ToString() + System.Environment.NewLine +
                      ex.Message, "Error al crear PDF",
                      MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
   
  • Formulario "formSQL.cs" (muestra consulta SQL para crear tabla para indexación de texto de PDF) :
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace AjpdSoftIndexarTextoFicherosPDF
{
    public partial class formSQL : Form
    {
        public formSQL()
        {
            InitializeComponent();
        }

        private void formSQL_FormClosed(object sender, FormClosedEventArgs e)
        {
            this.Dispose();
        }

        private void btCerrar_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btCopiarPortapapeles_Click(object sender, EventArgs e)
        {
            try
            {
                Clipboard.SetDataObject(txtSQL.SelectedText, true);
                MessageBox.Show("Texto copiado al portapapeles de Windows.",
                    "Copiado", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception err)
            {
                MessageBox.Show("Error al copiar texto al portapapeles: " +
                    Environment.NewLine + err.Message, "Error al copiar", 
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }
}
 
  • Formulario "formIndexarPDF.cs":
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Data.Odbc;


namespace AjpdSoftIndexarTextoFicherosPDF
{
    public partial class formIndexarPDF : Form
    {

        Utilidades util = new Utilidades();        
        
        public formIndexarPDF()
        {
            InitializeComponent();
        }

        private void btInsertarDocPDFIndexar_Click(object sender, EventArgs e)
        {
            dlAbrir.CheckFileExists = true;
            dlAbrir.CheckPathExists = true;
            dlAbrir.Multiselect = true;
            dlAbrir.DefaultExt = "pdf";
            dlAbrir.FileName = "";
            dlAbrir.Filter = "Archivos PDF (*.pdf)|*.pdf|Todos los archivos (*.*)|*.*";
            dlAbrir.Title = "Seleccionar fichero PDF a dividir y separar páginas";
            if (dlAbrir.ShowDialog() == DialogResult.OK)
            {
                lsPDFIndexar.Items.AddRange(dlAbrir.FileNames);
                for (int i = 0; i < lsPDFIndexar.Items.Count; ++i)
                    lsPDFIndexar.SetItemChecked(i, true);
            }         
        }

        private void btIndexarPDF_Click(object sender, EventArgs e)
        {
            if (lsPDFIndexar.CheckedItems.Count != 0)
            {
                string textoIndexadoPDFTodos = "";
                string textoIndexadoPDFActual = "";
                string ficheroPDFIndexar = "";
                string mMetadatos = "";
                int numElementos = lsPDFIndexar.CheckedItems.Count;

                this.Cursor = Cursors.WaitCursor;
                bp.Minimum = 0;
                bp.Maximum = numElementos - 1;
                bp.Value = 0;

                for (int i = 0; i <= lsPDFIndexar.CheckedItems.Count - 1; i++)
                {
                    ficheroPDFIndexar = lsPDFIndexar.CheckedItems[i].ToString();
                    bp.Value = i;
                    lInfo.Text = Convert.ToString(i + 1) +
                        "/" + Convert.ToString(numElementos) +
                        " [" + Path.GetFileName(ficheroPDFIndexar) + "]";
                    Application.DoEvents();
                    //obtener metadatos del fichero PDF
                    mMetadatos = util.obtenerMetaDatosFicheroPDF(ficheroPDFIndexar);
                    //obtener el texto del PDF
                    textoIndexadoPDFActual = util.obtenerTextoFicheroPDF(ficheroPDFIndexar);

                    if (textoIndexadoPDFTodos != "")
                    {
                        textoIndexadoPDFTodos = textoIndexadoPDFTodos +
                            Environment.NewLine + Environment.NewLine +
                            "==================================" +
                            Environment.NewLine + Environment.NewLine +
                            "Fichero: " + ficheroPDFIndexar + Environment.NewLine +
                            mMetadatos + Environment.NewLine + textoIndexadoPDFActual;
                    }
                    else
                    {
                        textoIndexadoPDFTodos =
                            "Fichero: " + ficheroPDFIndexar + Environment.NewLine +
                            mMetadatos + Environment.NewLine + textoIndexadoPDFActual;
                    }
                }
                txtResultadoIndexacionPDF.Text = textoIndexadoPDFTodos;
                this.Cursor = Cursors.Default;
                lInfo.Text = "Proceso de indexación de PDF finalizado";
                bp.Value = 0;
                MessageBox.Show("Proceso de indexación de PDF finalizado correctamente.",
                    "Fin proceso", MessageBoxButtons.OK, MessageBoxIcon.Information); 
            }
            else
            {
                btInsertarDocPDFIndexar.Focus();
                MessageBox.Show("Debe chequear los ficheros PDF a indexar a pantalla.", 
                    "Seleccionar PDF", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }

        private void btSelTodos_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < lsPDFIndexar.Items.Count; i++)
            {
                lsPDFIndexar.SetItemChecked(i, true);
            }
        }

        private void btNinguno_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < lsPDFIndexar.Items.Count; i++)
            {
                lsPDFIndexar.SetItemChecked(i, false);
            }
        }

        private void btInvertir_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < lsPDFIndexar.Items.Count; i++)
            {
                lsPDFIndexar.SetItemChecked(i, ! lsPDFIndexar.GetItemChecked(i));
            }
        }

        private void bConectar_Click(object sender, EventArgs e)
        {
            if (txtTabla.Text != "")  
            {
                try
                {
                    if (lsODBC.Text != "")
                    {
                        util.conexionBDODBC = new OdbcConnection("dsn=" + lsODBC.Text +
                            ";UID=" + txtUsuario.Text + ";PWD=" + txtContrasena.Text + ";");
                    }
                    else
                    {
                        if (txtPuerto.Text != "")
                        {
                            util.conexionBDODBC = new OdbcConnection("DRIVER={" + lsMotor.Text +
                                "};SERVER=" + txtServidor.Text + "; PORT=" + txtPuerto.Text +
                                ";UID=" + txtUsuario.Text +
                                ";PWD=" + txtContrasena.Text + ";" +
                                ";DATABASE=" + txtBD.Text + ";");
                        }
                        else
                        {
                            util.conexionBDODBC = new OdbcConnection("DRIVER={" + lsMotor.Text +
                                "};SERVER=" + txtServidor.Text + ";UID=" + txtUsuario.Text +
                                ";PWD=" + txtContrasena.Text + ";" +
                                ";DATABASE=" + txtBD.Text + ";");
                        }
                    }

                    util.conexionBDODBC.Open();

                    if (util.conexionBDODBC.State == ConnectionState.Open)
                    {
                        bDesconectar.Enabled = true;
                        bConectar.Enabled = false;

                        OdbcCommand comandoSQL;
                        string consultaSQL;

                        consultaSQL = "Select count(*) from " + txtTabla.Text;
                        try
                        {
                            comandoSQL = new OdbcCommand(consultaSQL, util.conexionBDODBC);
                            int numeroRegistros = Convert.ToInt32(comandoSQL.ExecuteScalar());
                            MessageBox.Show("La tabla " + txtTabla.Text + " existe con " +
                                Convert.ToString(numeroRegistros) + " registros.", "Conexión BD",
                            MessageBoxButtons.OK, MessageBoxIcon.Information);
                            beConectadoBD.Text = "Conectado a BD";
                            bDesconectar.Enabled = true;
                            bConectar.Enabled = false;
                        }
                        catch (Exception ex)
                        {
                            util.conexionBDODBC.Close();
                            bDesconectar.Enabled = false;
                            bConectar.Enabled = true;
                            MessageBox.Show("Error al ejecutar SQL: " +
                                System.Environment.NewLine + System.Environment.NewLine +
                                ex.GetType().ToString() + System.Environment.NewLine +
                                ex.Message, "Error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                    else
                    {
                        beConectadoBD.Text = "No conectado a BD";
                        bDesconectar.Enabled = false;
                        bConectar.Enabled = true;
                        MessageBox.Show("No conectado a la base de datos.", "Conexión BD",
                            MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    }
                }
                catch (Exception error)
                {
                    bDesconectar.Enabled = false;
                    bConectar.Enabled = true;
                    beConectadoBD.Text = "No conectado a BD";
                    util.conexionBDODBC.Close();
                    MessageBox.Show("Error de base de datos: " +
                        System.Environment.NewLine + System.Environment.NewLine +
                        error.GetType().ToString() + System.Environment.NewLine +
                        error.Message, "Error al crear PDF",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                
            }            
            else
            {
                MessageBox.Show("Debe indicar el nombre de la tabla de " +
                    "la BD donde se crearán los registros " +
                    "con el indexado del los PDF.", "Tabla",
                    MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                txtTabla.Focus();
            }            
        }

        private void btListaODBC_Click(object sender, EventArgs e)
        {
            SortedList listaODBC = new System.Collections.SortedList();
            lsODBC.Items.Clear();
            listaODBC = util.obtenerDataSourcesSistema();
            foreach (DictionaryEntry key in listaODBC)
            {
                lsODBC.Items.Add(key.Key.ToString());
            }
            listaODBC = util.obtenerDataSourcesUsuario();
            foreach (DictionaryEntry key in listaODBC)
            {
                lsODBC.Items.Add(key.Key.ToString());
            }
        }

        private void btGuardarTextoFichero_Click(object sender, EventArgs e)
        {
            dlGuardar.Title = "Selección de carpeta y fichero de " +
                "texto donde se guardará la indexación";
            dlGuardar.Filter = "Texto (*.txt)|*.txt|Todos los ficheros (*.*)|*.*";
            dlGuardar.DefaultExt = "txt";
            dlGuardar.FilterIndex = 1;
            dlGuardar.CheckFileExists = false;
            dlGuardar.OverwritePrompt = true;
            if (dlGuardar.ShowDialog() == DialogResult.OK)
            {
                try
                {
                    StreamWriter ficheroTexto = new StreamWriter(dlGuardar.FileName,
                        false, System.Text.Encoding.Default);
                    ficheroTexto.Write(txtResultadoIndexacionPDF.Text);
                    ficheroTexto.Flush();
                    ficheroTexto.Close();
                    MessageBox.Show("Fichero de texto guardado correctamente.", 
                        "Fichero guardado",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error al guardar fichero de texto: " +
                        System.Environment.NewLine + System.Environment.NewLine +
                        ex.GetType().ToString() + System.Environment.NewLine +
                        ex.Message, "Error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
        }

        private void bDesconectar_Click(object sender, EventArgs e)
        {
            try
            {
                util.conexionBDODBC.Close();
                bDesconectar.Enabled = false;                
                bConectar.Enabled = true;
                beConectadoBD.Text = "No conectado a BD";
                bConectar.Focus();
            }
            catch (Exception error)
            {
                bDesconectar.Enabled = false;
                bConectar.Enabled = true;
                MessageBox.Show("Error de base de datos: " +
                    System.Environment.NewLine + System.Environment.NewLine +
                    error.GetType().ToString() + System.Environment.NewLine +
                    error.Message, "Error al crear PDF",
                    MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btIndexarPDFBD_Click(object sender, EventArgs e)
        {
            if (util.conexionBDODBC.State == ConnectionState.Open)
            {
                if (lsPDFIndexar.CheckedItems.Count != 0)
                {
                    string textoIndexadoPDF = "";
                    string ficheroPDFIndexar = "";
                    string mMetadatos = "";
                    int numElementos = lsPDFIndexar.CheckedItems.Count;

                    this.Cursor = Cursors.WaitCursor;
                    bp.Minimum = 0;
                    bp.Maximum = numElementos - 1;
                    bp.Value = 0;

                    for (int i = 0; i <= numElementos - 1; i++)
                    {
                        bp.Value = i;
                        ficheroPDFIndexar = lsPDFIndexar.CheckedItems[i].ToString();
                        lInfo.Text = Convert.ToString(i + 1) +
                            "/" + Convert.ToString(numElementos) + 
                            " [" + Path.GetFileName (ficheroPDFIndexar) + "]";
                        Application.DoEvents();
                        //Obtener metadatos del fichero PDF
                        mMetadatos = util.obtenerMetaDatosFicheroPDF(ficheroPDFIndexar);
                        //obtener texto indexado del PDF
                        textoIndexadoPDF = util.obtenerTextoFicheroPDF(ficheroPDFIndexar);
                        util.insertarRegistroBD(ficheroPDFIndexar, textoIndexadoPDF,
                              mMetadatos, txtCampoFicheroPDF.Text, 
                              txtCampoTextoPDF.Text, txtCampoMetadatosPDF.Text,
                              txtTabla.Text, txtCampoFecha.Text, opBDIndexarReemplazar.Checked);                            
                    }
                    this.Cursor = Cursors.Default;
                    lInfo.Text = "Proceso de indexación de PDF finalizado";
                    bp.Value = 0;
                    util.conexionBDODBC.Close();
                    bConectar.Enabled = true;
                    bDesconectar.Enabled = false;
                    beConectadoBD.Text = "No conectado a BD";
                    MessageBox.Show("Proceso de indexación de PDF finalizado correctamente.",
                        "Fin proceso", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                else
                {
                    btInsertarDocPDFIndexar.Focus();
                    MessageBox.Show("Debe chequear los ficheros PDF a indexar a base de datos.",
                        "Seleccionar PDF", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            else
            {
                MessageBox.Show("Debe estar conectado a la base de datos para " +
                    "realizar la indexación de los ficheros PDF seleccionados.", 
                    "Error al crear PDF", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }


        private void formIndexarPDF_FormClosed(object sender, FormClosedEventArgs e)
        {
            Utilidades proUtilidades = new Utilidades();
            cifrarAES cifradoAES = new cifrarAES();
 
            proUtilidades.guardarValorConfiguracion("BD.ODBC", lsODBC.Text);    
            proUtilidades.guardarValorConfiguracion("BD.Motor", lsMotor.Text);
            proUtilidades.guardarValorConfiguracion("BD.Servidor", txtServidor.Text);
            proUtilidades.guardarValorConfiguracion("BD.Usuario", txtUsuario.Text);
            proUtilidades.guardarValorConfiguracion("BD.Contraseña", 
                cifradoAES.cifrarTextoAES (txtContrasena.Text,
                "AjpdSoft_Frase_Encriptado", "AjpdSoft_Frase_Encriptado", 
                "MD5", 22, "1234567891234567", 128));
            proUtilidades.guardarValorConfiguracion("BD.Base_Datos", txtBD.Text);
            proUtilidades.guardarValorConfiguracion("BD.Puerto", txtPuerto.Text);
            proUtilidades.guardarValorConfiguracion("BD.Tabla", txtTabla.Text);
            proUtilidades.guardarValorConfiguracion("BD.Campo_Texto_Indexado", 
                txtCampoTextoPDF.Text);
            proUtilidades.guardarValorConfiguracion("BD.Campo_Fecha", 
                txtCampoFecha.Text);    
            proUtilidades.guardarValorConfiguracion("BD.Campo_Metadatos", 
                txtCampoMetadatosPDF.Text);
            proUtilidades.guardarValorConfiguracion("BD.Campo_Fichero_PDF", 
                txtCampoFicheroPDF.Text);
        }

        private void btSQL_Click(object sender, EventArgs e)
        {
            formSQL frmSQL = new formSQL();
            frmSQL.ShowDialog();
        }

        private void formIndexarPDF_Load(object sender, EventArgs e)
        {                    
            Utilidades proUtilidades = new Utilidades();
            cifrarAES cifradoAES = new cifrarAES();

            lsODBC.Text = 
                proUtilidades.leerValorConfiguracion("BD.ODBC");
            lsMotor.Text = 
                proUtilidades.leerValorConfiguracion("BD.Motor");
            txtServidor.Text = 
                proUtilidades.leerValorConfiguracion("BD.Servidor");
            txtUsuario.Text = 
                proUtilidades.leerValorConfiguracion("BD.Usuario");
            txtContrasena.Text =
                cifradoAES.descifrarTextoAES(
                  proUtilidades.leerValorConfiguracion("BD.Contraseña"),
                  "AjpdSoft_Frase_Encriptado", "AjpdSoft_Frase_Encriptado", 
                  "MD5", 22, "1234567891234567", 128);
            txtBD.Text = 
                proUtilidades.leerValorConfiguracion("BD.Base_Datos");
            txtPuerto.Text = 
                proUtilidades.leerValorConfiguracion("BD.Puerto");
            txtTabla.Text= 
                proUtilidades.leerValorConfiguracion("BD.Tabla");
            txtCampoTextoPDF.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Texto_Indexado");            
            txtCampoFecha.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Fecha");
            txtCampoMetadatosPDF.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Metadatos");
            txtCampoFicheroPDF.Text = 
                proUtilidades.leerValorConfiguracion("BD.Campo_Fichero_PDF");
        }

        private void toolStripStatusLabel1_Click_1(object sender, EventArgs e)
        {
            //abrir navegador por defecto y acceder a la URL www.ajpdsoft.com
            System.Diagnostics.Process.Start("http://www.ajpdsoft.com");
        }
    }
}

 

Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF

En el ejemplo usaremos un servidor de base de datos con PostgreSQL. La aplicación AjpdSoft Indexar Texto PDF C# iTextSharpadmite cualquier motor de base de datos con soporte de ODBC: Oracle, MySQL, SQLite, Microsoft Access, Microsoft SQL Server, Firebird, PostgreSQL, etc.
A continuación mostramos algunos tutoriales para instalar PostgreSQL tanto en sistemas operativos Windows como Linux:
Una vez que tengamos disponible el servidor o equipo con el motor de base de datos y hayamos instalado el administrador pgAdmin III, abriremos este último, nos conectaremos al servidor. Pulsaremos con el botón derecho del ratón sobre "Databases", seleccionaremos "New Database":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
En la pestaña "Properties", en el campo "Name", introduciremos el nombre para la base de datos que usaremos para guardar el texto extraído de los ficheros PDF, por ejemplo "indexadopdf". Pulsaremos "OK":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Nuestra base de datos PostgreSQL aparecerá en el árbol, desplegaremos "indexadopdf" y accederemos a "Schemas", en "Public" pulsaremos con el botón derecho del ratón y seleccionaremos "New Object", en el submenú emergente pulsaremos en "New Table":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Introduciremos en la pestaña "Properties", en el campo "Name" el nombre para la tabla, por ejemplo "indexpdf":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Ahora añadiremos las columnas para la tabla "indexpdf", para ello pulsaremos en la pestaña "Columns" y pulsaremos "Add":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
En la pestaña "Properties" de la ventana "New Column", introduciremos el nombre para la columna, por ejemplo crearemos una columna con autoincremento que será la clave primaria de la tabla (primary key). En "Name" introduciremos "codigo" y en "Data type" seleccionaremos "serial". Pulsaremos "OK":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
De la misma forma, añadiremos la columna o campo "texto", con tipo de datos (Data type) "text". Este campo será el que guarde el contenido de texto de cada fichero PDF indexado. Por lo tanto debe ser un tipo de dato que admita cualquier texto de cualquier tamaño:
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Crearemos también el campo "metadatos" que será donde guardemos los metadatos extraídos del fichero PDF. Este campo no necesita ser de tipo "text" pues los metadatos no suelen tener más de 500 caracteres. Pero los metadatos pueden ser variables por lo que lo crearemos de tipo "text":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Crearemos también la columna "ficheropdf" que contendrá la ruta y nombre del fichero PDF indexado, esta columna puede ser de tipo de datos "character varying" y de tamaño 500 (Length):
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Añadiremos la columna "fechaindexacion" donde la aplicación guardará la fecha en la que realizó la extracción del texto del fichero PDF. Llamaremos a este campo "fechaindexacion" y de tipo "date":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Por último crearemo la clave primaria (primary key). Para ello desde la ventana de "New Table", pulsaremos en la pestaña "Constraints", seleccionaremos "Primary Key" y pulsaremos "Add":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Introduciremos el nombre para la clave primaria, por ejemplo "pk_codigo_indexacionpdf":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
En la pestaña "Columns", en "Column" seleccionaremos "codigo" y pulsaremos "Add":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Tras añadir la clave primaria pulsaremos "OK" en la ventana "New Primary Key":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
Tras crear las columnas y las constraints (restricciones) como la clave primaria, pulsaremos "OK" para crear definitivamente la tabla "indexpdf":
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
De esta forma ya tendremos la tabla "indexpdf" creada en la base de datos "indexadopdf" de nuestro servidor con PostgreSQL:
Crear base de datos y tabla en PostgreSQL para guardar indexación de PDF
La consulta SQL para crear la tabla anterior:
CREATE TABLE indexpdf
(
codigo serial,
texto text,
metadatos text,
ficheropdf character varying(500),
fechaindexacion date,
CONSTRAINT pk_codigo_indexacionpdf PRIMARY KEY (codigo)
)
WITH ( OIDS = FALSE ) ;

 

Crear origen de datos ODBC para acceso a PostgreSQL en PC con Windows 7

A continuación explicaremos cómo crear un origen de datos ODBC para acceso al servidor con PostgreSQL (puede ser Windows o Linux). Para crear un origen de datos ODBC de 64 bits (si hemos instalado el servidor con PostgreSQL x64) seguiremos los pasos que indica este tutorial:
Para aclarar el manido tema de los 64 ó 32 bits vamos a mostrar a continuación las posibles combinaciones, es importante conocerlas para saber qué ODBC instalar y cuál no. Por un lado el servidor de PostgreSQL, que puede tener un sistema operativo de 32 ó de 64 bits, si el sistema operativo es de 32 bits es evidente que PostgreSQL sólo podrá ser de 32 bits. Si el servidor tiene un sistema operativo de 64 bits podremos instalar PostgreSQL de 32 bits o PostgreSQL de 64 bits. Si instalamos PostgreSQL de 32 bits en el servidor los clientes (ODBC y demás tipos de conexión) deberán ser de 32 bits. Ahora bien, si nuestro servidor con PostgreSQL es de 64 bits e instalamos PostgreSQL de 64 bits tendremos las siguientes posibilidades en los equipos cliente que se conectarán a este servidor:
1. Aplicación cliente de 32 bits por lo que ésta sólo admitirá driver ODBC de 32 bits. Aunque tengamos el sistema operativo de 64 bits, en este caso deberemos instalar el v de 32 bits correspondiente para PostgreSQL. Aunque el servidor PostgreSQL sea de 64 bits, admitirá conexiones de un ODBC de 32 bits. En esta circunstancia hay que tener en cuenta que si el equipo cliente tiene como sistema operativo Microsoft Windows 7 x64 (válido para Windows Vista, Windows Server 2008 y Windows 8), para crear un origen de datos de 32 bits hay que ejecutar el fichero:
C:/Windows/SysWOW64/odbcad32.exe
Crear origen de datos ODBC para acceso a PostgreSQL en PC con Windows 7
El fichero anterior mostrará los orígenes de datos ODBC del equipo para 32 bits x86. Desde aquí podrá crearse un origen de datos ODBC de 32 bits que será el que pueda usar una aplicación cliente de 32 bits. Desde la pestaña "DSN de sistema" (para que el ODBC esté disponible para todos los usuarios) pulsaremos en "Agregar":
Crear origen de datos ODBC para acceso a PostgreSQL en PC con Windows 7
Seleccionaremos el origen de datos a usar, en nuestro caso "PostgreSQL ANSI". Por supuesto, antes de crear el origen de datos debe estar instalado el driver correspondiente (como ya hemos explicado aquí):
Crear origen de datos ODBC para acceso a PostgreSQL en PC con Windows 7
Introduciremos los datos para el nuevo origen de datos ODBC:
  • Data Source: nombre del origen de datos, por ejemplo "indexpdf".
  • Description: breve descripción del origen de datos, por ejemplo "Indexado de texto de ficheros PDF".
  • Database: nombre que le hayamos dado a la base de datos de PostgreSQL, en nuestro ejemplo "indexadopdf".
  • Server: IP o hosname del servidor con PostgreSQL.
  • Port: puerto para conexión con PostgreSQL, por defecto 5432.
  • User Name: nombre de usuario de PostgreSQL con permisos suficientes para acceso de consulta y modificación de la tabla en cuestión.
  • Password: contraseña para el usuario anterior.
Pulsando en el botón "Test" podremos realizar una prueba de conexión:
Crear origen de datos ODBC para acceso a PostgreSQL en PC con Windows 7
Si todo es correcto nos mostrará un mensaje con el texto "Connection successful":
Crear origen de datos ODBC para acceso a PostgreSQL en PC con Windows 7
 
2. Aplicación cliente de 64 bits, esta aplicación soportará drivers ODBC de 32 bits y de 64 bits, por lo tanto podremos crear el origen de datos en el equipo de la forma habitual, desde "Herramientas administrativas" - "Orígenes de datos ODBC", como indicamos aquí:
En el siguiente post de nuestros foros explicamos cómo crear una aplicación de 64 bits con Visual C# y explicamos también cómo crear un origen de datos ODBC de 64 o 32 bits:


Artículos relacionados

 

Créditos

Artículo realizado íntegramente por Alonsojpd miembro fundador del Proyecto AjpdSoft.