Pregunta

tengo un .NET 2.0 Control WebBrowser utilizado para navegar por algunas páginas sin interacción del usuario (no preguntes... larga historia).Debido a la naturaleza sin usuario de esta aplicación, he configurado la propiedad de supresión de scripterrorsss de 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 en el control ActiveX subyacente, no solo errores de script ". El artículo de MSDN Sin embargo, no menciona esto.Logré cancelar el evento NewWindow, que evita las ventanas emergentes, así que eso ya está solucionado.

¿Alguien tiene alguna experiencia usando uno de estos y bloqueándolo exitosamente? todo ¿Diálogos, errores de script, etc.?

EDITAR

Esta no es una instancia independiente de IE, sino una instancia de un control WebBrowser que se encuentra en una aplicación de Windows Form.¿Alguien tiene alguna experiencia con este control, o el subyacente? hachaSHDocVW?

EDITAR de nuevo

Lo siento, olvidé mencionar esto...Estoy tratando de bloquear un Alerta de JavaScript(), con solo un botón OK.Tal vez pueda convertir un objeto IHTMLDocument2 y acceder a los scripts de esa manera. He usado MSHTML un poco, ¿alguien lo sabe?

¿Fue útil?

Solución

Definitivamente esto es hacky, pero si trabajas con el control WebBrowser, te encontrarás haciendo muchas cosas hacky.

Esta es la forma más fácil que conozco de hacer esto.Necesita inyectar JavaScript para anular la función de alerta...algo parecido a inyectar esta función de JavaScript:

window.alert = function () { }

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

Como dije, hacky, pero funciona :)

Puedo entrar en más detalles si es necesario.

Otros consejos

Y para conocer una forma sencilla de inyectar esa línea mágica de JavaScript, lea cómo inyectar javascript en el control del navegador web.

O simplemente use este 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);
}

Quizás tengas que personalizar algunas cosas, echa un vistazo a IDocHostUIHandler, y luego consulte algunas de las otras interfaces relacionadas.Puede tener bastante 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 puedes hacer lo que quieras, pero requiere trastear en las partes internas de MSHTML y ser capaz de implementar las distintas COM interfaces.

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

IHostDialogHelper
IDocHostShowUI

Estas pueden ser las cosas que está considerando implementar.

Bloqueador de alertas a prueba de balas:

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 supone que tiene Microsoft.mshtml referencia agregada, "usando mshtml;" en sus espacios de nombres y Navegador es tuyo Navegador web instancia.

¿Por qué es a prueba de balas?Primero, maneja scripts dentro de marcos.Entonces eso no choca cuando un especial "marco asesino" existe en el documento.A "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 debe utilizar un bucle "for" más seguro con el bloque try/catch.

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

webBrowser1.ScriptErrorsSuppressed = true;

Simplemente agréguelo a su función de nivel de entrada.Después de mucha investigación, encontré este método y hasta ahora toco madera y ha funcionado.¡¡Salud!!

window.showModelessDialog y window.showModalDialog se pueden bloquear implementando la interfaz INewWindowManager; además, el código siguiente muestra cómo bloquear los cuadros de diálogo de alerta implementando 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;
    }
}

Acabo de publicar un artículo sobre Code Project que puede ayudarte.

Por favor mira - http://www.codeproject.com/KB/shell/WebBrowserControlDialogs.aspx

Espero que esto ayude.

El InjectAlertBlocker es absolutamente el código correcto 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);
}

Las referencias necesarias para agregar son

  1. Agregar una referencia a MSHTML, que probablemente se llamará "Biblioteca de objetos HTML de Microsoft" bajo COM referencias.

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

  3. Obtenga una referencia a los elementos de su script IHTMLElement:

Entonces puedes usar el Navigated evento 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();
}

¿Estás intentando implementar un robot web?Tengo poca experiencia en el uso del control de IE alojado, pero completé algunos proyectos Win32 y intenté usar el control de IE.La desactivación de las ventanas emergentes debe realizarse a través de los controladores de eventos del control como ya lo hizo, pero descubrí que también necesita cambiar 'Desactivar depuración de secuencias de comandos xxxx' en las opciones de IE (o puede modificar el registro en sus códigos) como Cjheath ya lo señaló.Sin embargo, también descubrí que era necesario realizar pasos adicionales para verificar la URL de navegación en busca de contenido descargable para evitar esos cuadros de diálogo de abrir/guardar.Pero no sé cómo lidiar con los archivos de transmisión porque no puedo omitirlos mirando solo las URL y al final recurrí a la biblioteca de Indy, ahorrándome todos los problemas al tratar con IE.Finalmente, recuerdo que Microsoft mencionó algo en línea de que IE no está diseñado para usarse como control OLE.Según mi propia experiencia, cada vez que el control navega a una nueva página se introducen pérdidas de memoria para los programas.

Tuve problemas mayores con esto:cargando una página web destinada a imprimir y muestra un molesto cuadro de diálogo Imprimir.El InjectBlocker fue la única forma que funcionó, pero bastante poco confiable.Bajo ciertas condiciones (estoy considerando que se debe a que el control WebBrowser usa el motor IE y esto depende de la versión de IE instalada), el cuadro de 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 cuadro de 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 muestre la página.Sin embargo lo intenté con:Propiedad DocumentText del control del navegador web 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 script Exec:

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

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

Esto pareció 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 );
  }
}

Simplemente desde las propiedades de control del navegador:scriptErrorSupressed=verdadero

La forma más sencilla de hacer esto es:En el :Webbrowser Control tienes el procedimiento (estándar) BeforeScriptExecute

(El parámetro para BeforeScriptExecute es pdispwindow )

Agrega esto :

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

De esta manera, antes de que se ejecute cualquier script, la alerta de la ventana de la página será suprimida por el código inyectado.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top