2008-09-16 15 views
17

Tengo un .NET 2.0 Control WebBrowser utilizado para navegar por algunas páginas sin interacción del usuario (no pregunte ... historia larga). Debido a la naturaleza sin usuario de esta aplicación, he establecido la propiedad ScriptErrorsSuppressed del control WebBrowser en verdadero, que la documentación incluida con los estados de VS 2005 "ocultará [...] todos sus cuadros de diálogo que se originan desde el control ActiveX subyacente". no solo errores de guiones ". El MSDN article no menciona esto, sin embargo. He logrado cancelar el evento NewWindow, que evita las ventanas emergentes, así que eso se solucionó.Cuadros de diálogo de bloqueo en el control .NET WebBrowser

¿Alguien tiene alguna experiencia en el uso de uno de estos y bloquea con éxito todos los diálogos, errores de secuencia de comandos, etc.?

EDITAR

Ésta no es una instancia independiente de IE, pero una instancia de un control WebBrowser que vive en una aplicación de Windows Forms. ¿Alguien tiene alguna experiencia con este control, o el subyacente, AxSHDocVW?

nuevo EDIT

En este momento se me olvidó mencionar esto ... Estoy tratando de bloquear una alerta de JavaScript(), con sólo un botón Aceptar. Tal vez puedo convertir un objeto IHTMLDocument2 y acceder a los scripts de esa manera, he usado MSHTML un poco, ¿alguien sabe?

+0

Consulte http://stackoverflow.com/questions/2476360 –

Respuesta

6

Esto definitivamente es hacky, pero si trabajas con el control WebBrowser, te encontrarás haciendo un montón de cosas estrafalarias.

Esta es la forma más fácil que conozco para hacer esto. Es necesario inyectar JavaScript para anular la función de alerta ... algo en la línea de inyección de esta función JavaScript:

window.alert = function() { } 

Hay muchas maneras de hacer esto, pero es muy posible hacerlo. Una posibilidad es enganchar una implementación de la interfaz DWebBrowserEvents2. Una vez hecho esto, puede conectarse a NavigateComplete, DownloadComplete o DocumentComplete (o, como lo hacemos, a alguna variación del mismo) y luego invocar un método InjectJavaScript que haya implementado que realice esta anulación de la ventana. método.

como he dicho, hacky, pero funciona :)

puedo entrar en más detalles si necesito.

0

¿Está tratando de implementar un robot web? Tengo poca experiencia en el uso del control de IE alojado, pero completé algunos proyectos de Win32 que intentaron usar el control de IE. La desactivación de las ventanas emergentes debe hacerse a través de los controladores de eventos del control como ya lo hiciste, pero me di cuenta de que también debes cambiar 'Deshabilitar la depuración de scripts xxxx' en las opciones de IE (o puedes modificar el registro en tus códigos) como cjheath ya lo señaló. Sin embargo, también encontré que era necesario realizar más pasos para verificar la URL de navegación en busca de contenido descargable para evitar esos diálogos de abrir/guardar. Pero no sé cómo lidiar con los archivos de transmisión, ya que no puedo omitirlos mirando solo las URL y al final recurrí a la biblioteca de Indy, lo que me ahorró todos los problemas al tratar con IE. Finalmente, recuerdo que Microsoft mencionó algo en línea que IE no está diseñado para usarse como control OLE. De acuerdo con mi propia experiencia, ¡cada vez que el control navega hacia una nueva página, introdujo fugas de memoria para los programas!

4

Es posible que deba personalizar algunas cosas, eche un vistazo a IDocHostUIHandler, y luego vea algunas de las otras interfaces relacionadas. Puede tener una buena cantidad de control, incluso hasta el punto de personalizar la visualización del diálogo/ui (no recuerdo qué interfaz hace esto). Estoy bastante seguro de que puede hacer lo que quiera, pero sí requiere hacer una inspección interna en el interior de MSHTML y poder implementar las diversas interfaces COM.

Algunas otras ideas: http://msdn.microsoft.com/en-us/library/aa770041.aspx

IHostDialogHelper 
IDocHostShowUI 

Estos pueden ser las cosas que usted está mirando la implementación.

+0

+1, pero en cualquier caso la implementación de IHostDialogHelper e IDocHostShowUI no bloquea las funciones 'confirm' y 'showModelessDialog' – walter

11

Y para una manera fácil de inyectar esa línea mágica de javascript, lea how to inject javascript into webbrowser control.

o simplemente utilizar el código completo:

private void InjectAlertBlocker() { 
    HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0]; 
    HtmlElement scriptEl = webBrowser1.Document.CreateElement("script"); 
    string alertBlocker = "window.alert = function() { }"; 
    scriptEl.SetAttribute("text", alertBlocker); 
    head.AppendChild(scriptEl); 
} 
+0

¿qué es 'element'? – dognose

+0

Se corrigió el error tipográfico (elemento-> scriptEl) – Sire

0

Logré inyectar el código anterior creando una clase extendida WebBroswer y anulando el método OnNavigated.

Esto parecía funcionar bastante bien:

class WebBrowserEx : WebBrowser 
{ 
    public WebBrowserEx() 
    { 
    } 

    protected override void OnNavigated(WebBrowserNavigatedEventArgs e) 
    { 
     HtmlElement he = this.Document.GetElementsByTagName("head")[0]; 
     HtmlElement se = this.Document.CreateElement("script"); 
     mshtml.IHTMLScriptElement element = (mshtml.IHTMLScriptElement)se.DomElement; 
     string alertBlocker = "window.alert = function() { }"; 
     element.text = alertBlocker; 
     he.AppendChild(se); 
     base.OnNavigated(e); 
    } 
} 
2

El InjectAlertBlocker es absolutamente correcto código es

private void InjectAlertBlocker() { 
    HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0]; 
    HtmlElement scriptEl = webBrowser1.Document.CreateElement("script"); 
    IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement; 
    string alertBlocker = "window.alert = function() { }"; 
    element.text = alertBlocker; 
    head.AppendChild(scriptEl); 
} 

Referencias necesaria a añadir es

  1. Añadir una referencia a MSHTML, que probablemente se denominará "Biblioteca de objetos HTML de Microsoft" bajo las referencias COM.

  2. Agregue using mshtml; a sus espacios de nombres.

  3. Obtener una referencia a su elemento de script IHTMLElement:

continuación, puede utilizar el evento Navigated del navegador web como:

private void InjectAlertBlocker() 
{ 
    HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0]; 
    HtmlElement scriptEl = webBrowser1.Document.CreateElement("script"); 
    IHTMLScriptElement element = (IHTMLScriptElement)scriptEl.DomElement; 
    string alertBlocker = "window.alert = function() { }"; 
    element.text = alertBlocker; 
    head.AppendChild(scriptEl); 
} 

private void webDest_Navigated(object sender, WebBrowserNavigatedEventArgs e) 
{ 
    InjectAlertBlocker(); 
} 
2
webBrowser1.ScriptErrorsSuppressed = true; 

Sólo añadir que a su función de nivel de entrada . Después de mucha investigación es cuando me encontré con este método, y tocar madera hasta ahora funcionó. ¡¡Aclamaciones!!

0

Tuve mayores problemas con esto: cargar una página web que está destinada a imprimir y muestra un cuadro de diálogo de Impresión molesto. InjectBlocker era la única forma que funcionaba, pero bastante poco fiable.Bajo ciertas condiciones (considero que es debido a que el control WebBrowser usa el motor de IE y esto depende de la versión de IE instalada) el diálogo de impresión aún aparece. Este es un problema importante, la solución funciona en Win7 con IE9 instalado, pero WinXP con IE8 muestra el diálogo, pase lo que pase.

Creo que la solución está en modificar el código fuente y eliminar el javascript de impresión, antes de que el control represente la página. Sin embargo, lo intenté con la propiedad DocumentText del control webbrowser y no funciona. La propiedad no es de solo lectura, pero no tiene ningún efecto cuando modifico la fuente.

La solución que encontré para mi problema es el guión Ejecutivo:

string alertBlocker = "window.print = function emptyMethod() { }; window.alert = function emptyMethod() { }; window.open = function emptyMethod() { };";  
this.Document.InvokeScript("execScript", new Object[] { alertBlocker, "JavaScript" }); 
5

a prueba de balas bloqueador de alerta:

Browser.Navigated += 
    new WebBrowserNavigatedEventHandler(
     (object sender, WebBrowserNavigatedEventArgs args) => { 
      Action<HtmlDocument> blockAlerts = (HtmlDocument d) => { 
       HtmlElement h = d.GetElementsByTagName("head")[0]; 
       HtmlElement s = d.CreateElement("script"); 
       IHTMLScriptElement e = (IHTMLScriptElement)s.DomElement; 
       e.text = "window.alert=function(){};"; 
       h.AppendChild(s); 
      }; 
      WebBrowser b = sender as WebBrowser; 
      blockAlerts(b.Document); 
      for (int i = 0; i < b.Document.Window.Frames.Count; i++) 
       try { blockAlerts(b.Document.Window.Frames[i].Document); } 
       catch (Exception) { }; 
     } 
    ); 

este ejemplo se supone que tiene Microsoft.mshtml añadió referencia ", usando mshtml; "en sus espacios de nombres y navegador es su WebBrowser instancia.

¿Por qué es a prueba de balas? Primero, es y maneja los guiones dentro de los marcos. Entonces, no falla cuando existe un especial "marco asesino" en el documento. Un "marco asesino" es un marco que genera una excepción al intentar usarlo como objeto HtmlWindow. Cualquier "foreach" utilizado en Document.Window.Frames provocaría una excepción, por lo que se debería utilizar un ciclo "for" más seguro con el bloque try/catch.

Quizás no sea la pieza de código más legible, pero funciona con páginas mal formadas de la vida real.

+0

Estaba buscando un código que itere sobre los cuadros para sobrescribir la alerta javascript. Este ha sido el único método que encontré para alcanzar mi objetivo. Gracias. –

2

window.showModelessDialog y window.showModalDialog pueden ser bloqueados mediante la implementación de la interfaz INewWindowManager, además, código de abajo muestran cómo bloquear los cuadros de diálogo de alerta mediante la implementación de IDocHostShowUI

public class MyBrowser : WebBrowser 
{ 

    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] 
    public MyBrowser() 
    { 
    } 

    protected override WebBrowserSiteBase CreateWebBrowserSiteBase() 
    { 
     var manager = new NewWindowManagerWebBrowserSite(this); 
     return manager; 
    } 

    protected class NewWindowManagerWebBrowserSite : WebBrowserSite, IServiceProvider, IDocHostShowUI 
    { 
     private readonly NewWindowManager _manager; 

     public NewWindowManagerWebBrowserSite(WebBrowser host) 
      : base(host) 
     { 
      _manager = new NewWindowManager(); 
     } 

     public int ShowMessage(IntPtr hwnd, string lpstrText, string lpstrCaption, int dwType, string lpstrHelpFile, int dwHelpContext, out int lpResult) 
     { 
      lpResult = 0; 
      return Constants.S_OK; // S_OK Host displayed its UI. MSHTML does not display its message box. 
     } 

     // Only files of types .chm and .htm are supported as help files. 
     public int ShowHelp(IntPtr hwnd, string pszHelpFile, uint uCommand, uint dwData, POINT ptMouse, object pDispatchObjectHit) 
     { 
      return Constants.S_OK; // S_OK Host displayed its UI. MSHTML does not display its message box. 
     } 

     #region Implementation of IServiceProvider 

     public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject) 
     { 
      if ((guidService == Constants.IID_INewWindowManager && riid == Constants.IID_INewWindowManager)) 
      { 
       ppvObject = Marshal.GetComInterfaceForObject(_manager, typeof(INewWindowManager)); 
       if (ppvObject != IntPtr.Zero) 
       { 
        return Constants.S_OK; 
       } 
      } 
      ppvObject = IntPtr.Zero; 
      return Constants.E_NOINTERFACE; 
     } 

     #endregion 
    } 
} 

[ComVisible(true)] 
[Guid("01AFBFE2-CA97-4F72-A0BF-E157038E4118")] 
public class NewWindowManager : INewWindowManager 
{ 
    public int EvaluateNewWindow(string pszUrl, string pszName, 
     string pszUrlContext, string pszFeatures, bool fReplace, uint dwFlags, uint dwUserActionTime) 
    { 

     // use E_FAIL to be the same as CoInternetSetFeatureEnabled with FEATURE_WEBOC_POPUPMANAGEMENT 
     //int hr = MyBrowser.Constants.E_FAIL; 
     int hr = MyBrowser.Constants.S_FALSE; //Block 
     //int hr = MyBrowser.Constants.S_OK; //Allow all 
     return hr; 
    } 
} 
0

simplemente de las propiedades de control del explorador: scriptErrorSupressed = true

0

la forma más sencilla de hacerlo es la siguiente: En el : control WebBrowser que tiene el procedimiento (estándar) BeforeScriptExecute

(El parámetro para BeforeScriptExecute es pdispwindow)

Añadir este:

pdispwindow.execscript("window.alert = function() { }") 

De esta manera, antes de cualquier ejecución del script en la ventana de alerta de la página será suprimido por el código inyectado.

Cuestiones relacionadas