Pergunta

Eu tenho um .NET 2.0 Controle WebBrowser usado para navegar em algumas páginas sem interação do usuário (não pergunte... longa história).Devido à natureza sem usuário deste aplicativo, eu configurei a propriedade ScripterRorsStrorsS da Web-Browser Control como True, que a documentação incluída nos estados VS 2005 [...] "ocultará todas as suas caixas de diálogo originárias que se originam do controle ActiveX subjacente, não apenas erros de script. " O Artigo MSDN não menciona isso, no entanto.Consegui cancelar o evento NewWindow, que evita pop-ups, então está resolvido.

Alguém tem alguma experiência usando um desses e bloqueando com sucesso todos diálogos, erros de script, etc?

EDITAR

Esta não é uma instância autônoma do IE, mas uma instância de um controle WebBrowser que reside em um aplicativo Windows Form.Alguém tem alguma experiência com esse controle, ou com o subjacente, AxSHDocVW?

EDITAR novamente

Desculpe, esqueci de mencionar isso...Estou tentando bloquear um Alerta JavaScript(), com apenas um botão OK.Talvez eu consiga lançar em um objeto IHTMLDocument2 e acessar os scripts dessa forma, já usei MSHTML um pouco, alguém sabe?

Foi útil?

Solução

Isso é definitivamente hacky, mas se você fizer algum trabalho com o controle WebBrowser, você se verá fazendo muitas coisas hackeadas.

Esta é a maneira mais fácil que conheço de fazer isso.Você precisa injetar JavaScript para substituir a função de alerta...algo como injetar esta função JavaScript:

window.alert = function () { }

muitas maneiras de fazer isso, mas é muito possível fazer.Uma possibilidade é enganchar uma implementação do DWebBrowserEvents2 interface.Feito isso, você pode conectar-se ao NavigateComplete, ao DownloadComplete ou ao DocumentComplete (ou, como fazemos, alguma variação dele) e, em seguida, chamar um método InjectJavaScript que você implementou que executa essa substituição do window.alert método.

Como eu disse, hacky, mas funciona :)

Posso entrar em mais detalhes se precisar.

Outras dicas

E para uma maneira fácil de injetar aquela linha mágica de javascript, leia como injetar javascript no controle do navegador.

Ou apenas 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);
}

Você pode ter que personalizar algumas coisas, dê uma olhada IDocHostUIHandler, e confira algumas das outras interfaces relacionadas.Você pode ter um bom controle, até o ponto de personalizar a exibição da caixa de diálogo/interface do usuário (não me lembro qual interface faz isso).Tenho certeza de que você pode fazer o que quiser, mas isso exige mexer no interior do MSHTML e ser capaz de implementar os vários COM interfaces.

Algumas outras ideias:http://msdn.microsoft.com/en-us/library/aa770041.aspx

IHostDialogHelper
IDocHostShowUI

Essas podem ser as coisas que você está pensando em implementar.

Bloqueador de alerta à prova 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 exemplo pressupõe que você tenha Microsoft.mshtml referência adicionada, "usando mshtml;" em seus namespaces e Navegador é seu Navegador da Web instância.

Por que é à prova de balas?Primeiro, é lida com scripts dentro de frames.Então isso não trava quando um especial "quadro matador" existe no documento.A "quadro matador" é um quadro que gera uma exceção na tentativa de usá-lo como objeto HtmlWindow.Qualquer "foreach" usado em Document.Window.Frames causaria uma exceção, portanto, um loop "for" mais seguro deve ser usado com o bloco try/catch.

Talvez não seja o código mais legível, mas funciona com páginas mal formadas da vida real.

webBrowser1.ScriptErrorsSuppressed = true;

Basta adicionar isso à sua função de nível de entrada.Depois de muita pesquisa, me deparei com esse método, e toquei na madeira até agora funcionou.Saúde!!

window.showModelessDialog e window.showModalDialog podem ser bloqueados implementando a interface INewWindowManager. Além disso, o código abaixo mostra como bloquear caixas 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;
    }
}

Acabei de publicar um artigo no Code Project que pode te ajudar.

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

Espero que isto ajude.

O InjectAlertBlocker está absolutamente correto, o código é

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);
}

As referências necessárias a serem adicionadas são

  1. Adicione uma referência a MSHTML, que provavelmente será chamado de "Biblioteca de objetos HTML da Microsoft" sob COM referências.

  2. Adicionar using mshtml; para seus namespaces.

  3. Obtenha uma referência ao seu elemento de script IHTMLElement:

Então você pode usar o Navigated evento do navegador da 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();
}

Você está tentando implementar um robô web?Tenho pouca experiência no uso do controle hospedado do IE, mas concluí alguns projetos Win32 e tentei usar o controle do IE.A desativação dos pop-ups deve ser feita através dos manipuladores de eventos do controle como você já fez, mas descobri que você também precisa alterar o 'Desativar depuração de script xxxx' nas opções do IE (ou você pode modificar o registro em seus códigos) como cjheath já apontou.No entanto, também descobri que etapas extras precisavam ser executadas para verificar o URL de navegação em busca de qualquer conteúdo para download, para evitar essas caixas de diálogo de abrir/salvar.Mas não sei como lidar com arquivos de streaming, pois não posso ignorá-los olhando apenas os URLs e no final recorri à biblioteca Indy, poupando-me de todos os problemas de lidar com o IE.Finalmente, lembro que a Microsoft mencionou algo online que o IE não foi projetado para ser usado como um controle OLE.De acordo com minha própria experiência, toda vez que o controle navegava para uma nova página introduzia vazamentos de memória para os programas!

Eu tive problemas maiores com isso:carregando uma página da web destinada à impressão e exibe uma caixa de diálogo de impressão irritante.O InjectBlocker foi a única maneira que funcionou, mas pouco confiável.Sob certas condições (estou considerando que o controle do WebBrowser usa o mecanismo do IE e isso depende da versão do IE instalada), a caixa de diálogo de impressão ainda aparece.Este é um grande problema, a solução funciona no Win7 com o IE9 instalado, mas o WinXP com o IE8 exibe a caixa de diálogo, não importa o que aconteça.

Acredito que a solução está em modificar o código fonte e remover o javascript de impressão, antes que o controle renderize a página.No entanto, tentei isso com:Propriedade DocumentText do controle do navegador da web e não está funcionando.A propriedade não é somente leitura, mas não tem efeito quando modifico a fonte.

A solução que encontrei para o meu problema é o script Exec:

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

Consegui injetar o código acima criando um arquivo estendido WebBroswer classe e substituindo o OnNavigated método.

Isso pareceu funcionar muito bem:

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 );
  }
}

Simplesmente nas propriedades de controle do navegador:scriptErrorSupressed=true

A maneira mais fácil de fazer isso é:No :Controle do navegador da Web você tem o procedimento (padrão) BeforeScriptExecute

(O parâmetro para BeforeScriptExecute é pdispwindow )

Adicione isso :

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

Desta forma, antes de qualquer execução de script na janela da página, o alerta será suprimido pelo código injetado.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top