Limitaciones de control de Webbrowser

Estoy usando el control WebBrowser en un proyecto de Windows forma C # y quería saber si hay limitaciones de cuántas instancias de dicha aplicación puede ejecutar al mismo tiempo. (en otras palabras, MSFT impone limitaciones que no sean límites físicos de la máquina: CPU / memoria, etc.)

No hay limitaciones artificiales en el control WebBrowser .

Sin embargo, utiliza el motor de renderizado de IE (cualquiera que sea la versión instalada en la computadora del usuario final), por lo que utiliza bastante memoria.

¿Que estás tratando de hacer?

Si intentas escribir un navegador web, te recomiendo que uses un mejor motor de renderizado, como WebKit o Gecko .

Déjame contarte algunas desventajas …

[la mayoría de los problemas mencionados aquí han sido respondidos o tratados en cierta medida en mi sección de respuestas anteriores en StackOverflow, si tiene curiosidad, siéntase libre de navegar por mis respuestas relacionadas con WebBrowser-Control].

  1. Detectar cuándo la página está realmente terminada de cargar es muy difícil de hacer confiablemente, de hecho, tienes que emplear una serie de hacks para poder hacer esto, algunos métodos e ideas ni siquiera se hablan en línea y no se conocen , pero los años que he pasado luchando con este control, he descifrado algunas cosas y he desarrollado una base de código para hacerlo funcionar. Y lo hace, si necesita ayuda con esto, puedo proporcionar más detalles.

  2. Déjame decirte esto directamente. El motor de representación predeterminado en el control del navegador web se repara para garantizar la compatibilidad en todas las plataformas.

    Básicamente, si el navegador instalado es IE 7 – IE 9, entonces el motor de renderizado utilizado es IE 7.0 solamente (por defecto).

    Sin embargo, si su versión de IE instalada es IE 6 o inferior, entonces el motor de renderizado utilizado es IE 4.0 (no es broma), a menos que, por supuesto, lo configure de otra manera.

    Existe la idea errónea de que el control WebBrowser utiliza lo que está actualmente instalado (versión actual de IE), pero esto no es cierto, ya que lo hacen para reducir los problemas de compatibilidad con versiones anteriores. Puede ver (como prueba) que este es realmente su problema yendo a http://www.whatsmyuseragent.com en su navegador normal, y luego ir de nuevo a ese sitio web en su control WebBrowser, verá que dice MSIE 7.0 :).

    Puede configurarlo para usar la versión instalada actual de Internet Explorer, ya sea usando una etiqueta META in-page, o editando el Registro en la máquina donde se ejecutará el control del webbrowser (la edición para Current_User y Local_Machine funcionará).

    Por lo tanto, por razones de compatibilidad, renderizará las páginas en el modo estándar IE7 de manera predeterminada. Para evitar que esto suceda, siga el enlace que he proporcionado a continuación que analizará tanto el método META Tag como el método de edición del registro para resolver este problema (tanto para sistemas de 32 como de 64 bits). La solución se incluye como una respuesta a la pregunta de otra persona sobre una función que funciona de forma incorrecta o inesperada. Leer la pregunta no es necesario para interpretar / entender correctamente la respuesta. Aqui esta el link:

    La secuencia de comandos se ejecuta más lentamente en el control de WebBrowser de dotnet (Ctrl + clic para abrir en la nueva pestaña).

  3. El sistema de eventos es bastante hacky, realmente necesita saber cosas que no se han documentado correctamente y algunas cosas que no se han documentado en absoluto. De hecho, lo he declarado como uno de los peores productos de MS, en términos del diseño del producto y también en términos de la falta de documentación decente que han puesto a disposición en él. Su documentación seca de estilo MSDN es ridícula.

  4. Compatibilidad con marcos incorrectos, si haces una llamada a document.frames.length, solo obtendrás los marcos justo debajo del documento de nivel superior, no todos los marcos, necesitarás escribir tus propias funciones para obtener todos los cuadros nesteds (infinitamente nesteds) y he hecho esto, si necesita ayuda con eso. La detección y referencia de marcos es muy importante y juega un papel vital para detectar cuándo la página realmente ha terminado de cargarse. En eso, usar .Busy y .ReadyState en el control WebBrowser no es suficiente. De hecho, no es suficiente.

  5. No existe un sistema incorporado para deshacerse de los cuadros de diálogo de JavaScript que aparecen en cada página, incluido el nuevo cuadro de diálogo IE9 que molesta a las personas con el mensaje “¿Estás seguro de que quieres abandonar esta página?”. He desarrollado rutinas para hacer esto y deshacerme de ellas, básicamente, uno de los métodos consiste en ejecutar JavaScript enviado desde el control WebBrowser a la página html que lo dirige para eliminar la alerta, confirmar, imprimir cuadros de diálogo (y también para obtener deshacerse del nuevo cuadro de diálogo IE 9 que mencioné anteriormente). Estos son posibles cuadros de diálogo provenientes solo de JS, y básicamente ejecuto JavaScript que le dice al navegador que la función .alert es nula (es decir, un método / función vacía que no hace nada), y hago exactamente lo mismo para todos estos 4 cuadros de diálogo que provienen de JavaScript. Por supuesto, si ha contado más de 4 cuadros (si ha contado más, no dude en hacérmelo saber). Además, hay un segundo método mediante el cual podemos hacer esto, y no solo evitará los cuadros de diálogo de JavaScritp, sino que cada cuadro de diálogo que podría / debería aparecer en el control del navegador web, este método usa WinHooks e intercepta el cuadro de diálogo antes se muestra, puede obtener tanta información como desee del cuadro de diálogo (su contenido como texto, título / título como texto, etc.) y decidir si desea que se muestre o cancelar su visualización, o incluso simular un clic en cualquier parte del cuadro de diálogo (es decir: cualquiera de sus botones) para que la stack piense que el diálogo de pregunta o información fue respondido correctamente. Este es un método interesante que he leído pero que aún no he probado, y estoy ansioso por comprender el proceso WinHook una vez que tenga algo de tiempo libre. Como de costumbre, si necesita ayuda, no dude en consultar algunas de mis respuestas anteriores a varias preguntas de control del navegador web, ya que he respondido muchas, y si eso no funciona, hágamelo saber. Tenga en cuenta que esto depende en gran medida de saber cuándo la página está completamente cargada, lo cual es muy difícil de hacer (pero es posible, utilizando métodos no documentados, de una manera 100% confiable). Entonces punto 1). Entrará en relevancia muchas veces.

  6. No existe una forma confiable o fácil de controlar la información de almacenamiento en caché que se perpetúa o guarda, una vez más, debe desarrollar sus propias rutinas para hacer lo que quiera con la información de almacenamiento en caché, ya sea para filtrar, eliminar o tratar de evitarlo para todo el caché tipos, incluida la información del historial, las cookies y los archivos de caché reales almacenados en el sistema local. Si nos fijamos en DeleteUrlCacheEntry que le dará una pista sobre dos formas de hacerlo por su cuenta, también, estoy bastante seguro de que tengo algunas respuestas anteriores que hablan sobre cómo hacer esto en StackOverflow. Con DeleteUrlCacheEntry, puede jugar con elementos de caché que comienzan con la etiqueta “Cookie:”, la etiqueta “Visited:” y los elementos que son simplemente direcciones de sitios web (comenzando con “http: //” y “https: //” (y sí, https está en caché; | al menos la información de ubicación es de todos modos.) También tenga en cuenta que esta información disponible a través de DeleteUrlCacheEntry (y la FindFirstUrlCacheEntry / FindNextUrlCacheEntry que se utiliza para recorrer todo el caché) no incluye su Internet actual elementos del historial del explorador. La lista de sitios “Visitado:” está separada de su lista de Historial real, que ve cuando hace clic en el símbolo * en la barra de menús de Internet Explorer y entra en la sección Historial (de la sección de favoritos). no estoy seguro de por qué lo han hecho así y cuál es la diferencia formal y exacta (y por qué hay una diferencia) pero está en la lista de cosas para descubrir (no dude en hacérnoslo saber en los comentarios). Porque, la La lista “Visitado:” es una lista de sitios que usted visitó, y el historial de IE es prácticamente una lista de sitios web que también ha visitado. No creo que hagan una distinción de los sitios que ha ingresado y escrito manualmente, en comparación con los bits que se recuperan automáticamente por la página HTML o su navegador (como a través de iframes, etc., y redirecciones automáticas, ventanas emergentes, etc.) … así que me resulta difícil entender cuál es la distinción, y actualizaré este bit una vez que lo descubra.

  7. Al anular el agente de usuario predeterminado no está integrado correctamente, puede pasar su propio agente de usuario en el método de navegación, pero una vez que el usuario navega allí, el sitio obtendrá los detalles del agente de usuario de los progtwigs como usted ha configurado, sin embargo, este ganó no perpetuar Entonces, una vez que el usuario sigue un enlace en la página navegada, el control WebBrowser continuará enviando el agente de usuario real (real) que el control WB está usando para renderizar su sitio, a menos que, por supuesto, intercepte la navegación, cancélela y vuelva a navegar usando el método .navigate nuevamente al enviar su propio agente de usuario (nuevamente). Esto no podrá dar cuenta de cosas como imágenes y archivos de tags LINK, etc., ya que no obtendrá BeforeNavigate eventos para estos, por lo que no puede interceptarlos y modificar los encabezados enviados para ellos. En su lugar, debe utilizar una solución externa mediante la importación de algunas funciones externas urlmon.dll: esto puede hacerlo al 100% y funciona a la perfección, sin embargo, es otra dependencia añadida (pero urlmon.dll se incluye con todas las versiones de Windows relevantes hasta la fecha).

  8. No hay ninguna propiedad o método de “redirigir toda mi actividad de control de WB a este marco en particular”, aunque puede y deberá desarrollar eso si lo desea o necesita, el único soporte de marco es un argumento TargetFrameName que viene con el .navigate método, y tendrá que obtener una referencia y dirigir todo lo que hace allí manualmente, para cada acción que debe estar sucediendo allí, ya que los usuarios pueden hacer clic en las cosas desde cualquier marco y no tendrían ni idea ni pista a menos que revisen para ello.

  9. Protección de fotogtwigs cruzados para sitios con marcos que apuntan a dominios externos: como usted sabrá, si tiene una página en abc.com y tiene un marco flotante que tiene una fuente de un dominio llamado xzy.com (como lo hacen la mayoría de los anunciantes al retransmitir contenido de sus propios servidores), se encontrará con problemas de seguridad de dominio entre cuadros si intenta acceder a ese marco, independientemente de los privilegios elevados con los que se ejecuta su aplicación. Es una tontería, y ni siquiera le informarán al respecto, en su lugar, su documento de referencia que apunta al marco simplemente no tendrá datos y no podrá usarlo y el control WB no le dirá por qué. Todo lo que tendrá acceso es la URL de origen del marco y eso es todo, nada dentro de él. ¿Solución? Bueno, hay un TypeLib registrable en su máquina que puede usar para anular esto, no integrado en el control WB, y ni siquiera incorporado en su propia interfaz de progtwigción, de hecho es una rutina C externa que necesita usar al hacer referencia. y registrar el TypeLib (no estoy seguro de si hay una nueva forma de hacerlo sin este método en .NET ahora mismo días). Sin embargo, también necesitará escribir código alrededor de este TypeLib en su entorno de progtwigción actual (código excesivo para usar el material en el registro TypeLib, así que no se trata solo de llamar a una función, sino de escribir más código alrededor de esa función que Estaré usando).

  10. Activar / desactivar JavaScript, activar / desactivar la configuración de navegación, como los sonidos de navegación, etc. Si está escribiendo un progtwig extractor web, los sonidos de navegación volverán locos a sus usuarios, activar o desactivar estas opciones no está integrado en el control WebBrowser , puede cambiar las cosas de manera global usando el registro si es necesario, y luego cambiarlas una vez hecho. Tendrá que buscar valores reg para cada una de estas configuraciones / opciones relacionadas con la configuración de Internet. Hay formas de hacer esto para su instancia de aplicación, importando rutinas desde InternetSecuritySettings, creo, pero una vez más, no integrado en WB, y solo otra serie de hacks para agregar a la lista.

  11. Por supuesto, deberá detectar si existe una conexión a Internet y si hay una disponible. El control WB ni siquiera te da un atisbo de esperanza al hacer esto, a pesar de que es una parte vital para que funcione. Por lo tanto, si no desea que las molestas ventanas emergentes de la conexión de acceso telefónico MS (para aquellos que usan acceso telefónico) o el asistente de Internet para aquellos en otras conexiones, aparezca CADA VEZ QUE SU CONTROL WB TRATE DE HACER UNA CONEXIÓN o intente navegar en algún lugar, entonces necesitarás usar un control para tratar de verificar las conexiones manualmente, y este control tendrá que ser un control externo a MS, y un control que no tiene la API de MS en su núcleo (ya que las API de Internet de MS son las API que activan estos cuadros emergentes para la conexión a Internet). Por lo tanto, deberá obtener un control de tipo winsocks externo escrito desde cero que no use winsocks, aprender a usarlo y usarlo para tratar de verificar si Internet está conectado antes de cada vez que realice una acción con el WB. controlar.

  12. Obtendrá muchos mensajes de “Error de automatización” o “Error no especificado”, donde ni siquiera le dice qué salió mal, cuando se trata de elementos en un documento / página html en vivo, estos suelen ser cuando hay html que se realiza de una manera no recomendada, a pesar de que es una forma que un navegador puede tratar y leer, y trata de manera regular. Por ejemplo, si tiene un enlace Anchor con target = _top y no tiene comillas alrededor de la parte _top, aunque los navegadores entiendan esto y se comporten como se espera, el control del navegador web arrojará sus manos al air y se dará por vencido, arrojando un “error no especificado”, sin siquiera decirle de qué es tan exigente. Por lo tanto, deberá asegurarse de que el elemento esté escrito así: target = “_ top” para que el control de WB se comporte, y hacer estos cambios en cada documento en vivo puede ser tedioso, y necesitará escriba rutinas generales para hacer esto para cada página si lo necesita: rutinas que se ejecutan después de que el documento está cargado por completo (que deberá detectar de manera confiable para poder hacerlo). Si tuviera que elegir lo más difícil de hacer correctamente con el control WB, tendría que estar detectando cuándo la página está completa y se carga completamente, de manera confiable. Además de eso, es lo más importante que tendrá que hacer también, con el control de WB, ya que casi todo depende de la detección precisa de esto.

  13. Necesita un objeto de historial separado, porque si elige “sin historial” durante la navegación o encuentra una forma de hacer que la navegación sin historial funcione, puede estar seguro de que no funcionará retroceder o avanzar a estas páginas (es decir, llamadas). GoBack o .GoForward a estas páginas y direcciones). Una vez que elimine del historial, o especifique que no se guardará ningún historial para esto o para una navegación particular, regresar allí es imposible a menos que vuelva a navegar a esa página. Deberían haber conservado una lista de historial en memoria que debería haber estado disponible para volver a ella aunque la página se haya eliminado del historial global (que es la única forma en que se realiza la búsqueda sin historial). Por lo tanto, si intenta regresar, obtendrá (además de todo) un error de tiempo de ejecución, y solo en los últimos días de .NET proporcionó un método llamado .CanGoBack para verificar si puede regresar o no, antes de esa fecha. (si usa pre.NET) debería tener que escribir el código al respecto o tratar de mantener el conteo de dónde estaba (lo cual no es fácil, pero sí factible).

Puedo continuar (creo) pero lo dejaré así por ahora, sin embargo, aparte de esas cosas, es un control bastante bueno y abre la puerta a un mundo completamente nuevo de aplicaciones e ideas que puedes hacer que suceda . Como he señalado en algunos de estos puntos, estos son todos los problemas que he resuelto (y todavía hay más, que he resuelto cuando se necesitaba una solución), así que si tiene alguna pregunta o necesita ayuda, deje que ya sé que estaría feliz de al menos tratar de ayudarte.

Cuando estaba tratando de entender esto, no había nadie cerca para ayudarme, ya que nadie realmente sabía mucho sobre este control, así que tuve que resolverlo poco a poco, uno por uno. Desde entonces, ha ganado popularidad, y hay más personas que lo usan (especialmente desde que la versión .NET ha proporcionado mejoras incrementales). Por lo tanto, estaría encantado de ayudar a cualquiera que se encuentre en la situación en la que he estado antes, ya que recuerdo que era un lugar aterrador y solitario, y MS no hizo ninguna documentación sabia. Es solo algo que desarrollaron para uso interno y dejaron que otros lo usaran, al tiempo que proporcionaban solo una lista de argumentos / parámetros de entrada / salida y lista de valores devueltos para todas las propiedades, métodos y eventos, y eso era todo, sin significado ni contexto o ejemplos de código real asociados con él, seguramente, nada documental en cuanto a la resolución del conjunto de problemas que conlleva.

Ok, eso lo hace por ahora, estaría interesado en las opiniones de las personas sobre este control y uso de él, así que siéntete libre de dejar un comentario. Cuídate. Erx.

Pruebe este código y vea lo que sucede:

 int count = 0; List
forms = new List
(); try { while (true) { Form f = new Form(); WebBrowser wb = new WebBrowser(); f.Controls.Add(wb); f.Show(); wb.Url = new Uri(@"http://www.stackoverflow.com"); forms.Add(f); count++; } } catch { MessageBox.Show(count.ToString()); }

Voy a adivinar que son cientos, pero no sé.