lunes, 3 de noviembre de 2008

Buenas noches mis cinco lectores. Disculparan ustedes que los aburra de nuevo con una entrada de programación. Hagan una flamewar de comentarios fanboys si se aburren.


Resulta que como ya comente antes cree un explorador web personalizado para automatizar unos procesos de unas páginas web que son repetitivos y muy comunes para que me paguen a mi en lugar de a un mono que haga esos rutinarios trabajos. Para hacer esto, inclui en mi aplicación un control ActiveX WebBrowser para manejar el nucleo de Internet Explorer (en este caso el la versión 6) dentro de un formulario, y más importante poder manipular los eventos del explorador (especialmente importante para mi caso es el evento DocumentComplete) y manipular el DOM de las páginas cargadas en mi aplicación para controlar los procesos y manipular su contenido a mi conveniencia. Era lo que estaba a la mano en lugar de construir algo más sofisticado con APIs y a más bajo nivel como uno similar que tenemos en C++ pero es más complejo de entender y dificil de adaptar a casos rebuscados.


El pero esta en que resulta que IExplorer realiza muchas conexiones para abrir la página y el servidor web lo reciente y si la cantidad de trabajo es muy masiva las salidas se saturan. En cambio FireFox para hacer lo mismo solo necesita menos de una cuarta parte del total de conexiones. ¿Qué hace IE con tantas conexiones? ¿Le envia reportes a Redmond de lo que hacemos? No se, pero para 1'000 procesos el IE realiza 30'000 conexiones o más al servidor web mientras que FireFox apenas no anda sobre las 5'200 o menos para las mismas tareas.


¿Es posible usar a FireFox dentro de la aplicación?


Pues si, encontre una manera muy sencilla de hacerlo recurriendo a un ActiveX preparado para cumplir la función del ActiveX de IE ya existente. Lo he probado y en lo general funciona. Advierto de una vez que no es un substituto 1:1 totalmente funcional. Hay diferencias como las hay entre IE y FireFox, ademas de que se nota que le falta trabajo en las cosas más dificiles de implementar. Es decir, para navegación esta bien, pero por lo pronto para manipulación del DOM no he obtenido resultados ya sea por mi desconocimiento de equivalencias o porque estos metodos no estan desarrollados aun o tal vez nunca. Debido a estos inconvenientes es que la investigación continua, pero por lo pronto ya tengo algo interesante. Un WebBrowser personalizado usando el motor de Mozilla, lo cual me parece interesante a mi porque combinando el motor de Mozilla en lugar de IE, usando MONO en lugar de NetFramework y GTK# en lugar de Windows forms podria desarrollar las versiones futuras de modo que sean multiplataforma por lo menos para curiosidad mia. Ademas, entre SharpDevelop que estoy usando ultimamente y MonoDevelop no hay muchas diferencias porque son, como la versión multiplataforma de un IDE común.


FireFox, GTK, MONO


¿Combinación adecuada?


Ahora a lo que te truje. El ActiveX para manejar el motor de Mozilla lo encontre en esta página, desde donde pueden descargar la instalación, que no es otra cosa que la parte indispensable de Gecko (el motor de renderizado) y un registrador de .dll para que puedas usarlas desde los IDE de programación como un control más. Yo estoy usando la versión "Mozilla ActiveX Control 1.7.12" en combinación con FireFox 3. Para integrarlas a Visual estudio solo tuve que agregar una herramienta más en la pestaña de componentes de la caja de herramientas, buscar la .dll entre los componentes COM (previamente he corrido el instalador, claro) y ¡Voila! Ya tengo el control en mi toolbox para agregarlo solo con click y arrastre como cualquier caja de texto. También se pueden integrar a otros IDE para otros lenguajes no .NET y en la página arriba referenciada hay instrucciones para Visual Studio, C++ por código, Delphi y Visual Basic 6.


Si optas por construir desde cero, solo hay que manejar el control y sus eventos como a cualquier otro control de Visual Studio, y es identico en casi todo al de Microsoft incluido en mshtml.dll, hasta se agregan igual a la barra de herramientas, y por eso en aplicaciones existentes basta con borrar los controles de IE, poner en su lugar uno nuevo de FireFox y ponerle el mismo nombre que el anterior, aunque en este caso necesite regenerar los eventos manualmente; y claro. También las referencias a los espacios de nombres AxMOZILLACONTROLLib y MOZILLACONTROLLib


El manejo de este ActiveX es muy similar al de IExplorer, por ejemplo. La declaración del control:

// Declarar el control ActiveXWebBrowser para IExplorer
AxSHDocVw.AxWebBrowser browser = new AxSHDocVw.AxWebBrowser()
// Declarar el control ActiveXWebBrowser para Mozilla
AxMOZILLACONTROLLib.AxMozillaBrowser browser = new AxMOZILLACONTROLLib.AxMozillaBrowser()

Lo unico que cambia es el nombre del objeto y la .dll referenciada. Pero que eso no te engañe, aunque a primera vista y aunque el debuger no te arroje errores, en el evento .Navigate hay un detalle.

// Abrir la página de NGA
browser.Navigate("http://gamersla.net/", ref objeto, ref objeto, ref objeto, ref objeto);

En este caso, para IE dos de ellos son tipo object con valor cero y dos son cadenas de caracteres (string) vacias. En cambio, al tratar de usarlo así para Mozilla, solo obtenia ventanas en blanco. Para que el FireFox funcionara tuve que enviar cuatro null de tipo object y entonces si trabajo bien.


ActiveX Mozilla Firefox


Aplicación que utiliza el ActiveX para usar a Mozilla


Construi para hacer pruebas una aplicación sencilla, no es más que una ventana WindowsForm con el control ActiveX para usar a Mozilla donde se abre una página dada como parametro por linea de comando. Les comparto:

El código fuente
El ejecutable de prueba

Ya puedo abrir las páginas, ahora lo que toca es tratar de controlar el DOM y poder hacer cambios y autosubmit en la página controlando los eventos del browser.

0 comentarios:

Publicar un comentario

Por favor trata de escribir bien, no te pido que no te falte ni un acento pero por favor evita escribir como metroflogger o facebookero. Este blog es un sitio decente. Gracias.

Subscribe to RSS Feed Follow me on Twitter!