Question

Je dispose d'un contrôle .NET 2.0 WebBrowser utilisé pour naviguer sur certaines pages sans interaction de l'utilisateur (ne demandez pas ... histoire longue). En raison de la nature sans utilisateur de cette application, j'ai défini la propriété ScriptErrorsSuppressed du contrôle WebBrowser sur true. La documentation fournie avec VS 2005 indique [...] qu'elle "masquera toutes ses boîtes de dialogue issues du contrôle ActiveX sous-jacent. , pas seulement des erreurs de script. " Article MSDN ne mentionne pas cela, cependant. J'ai réussi à annuler l'événement NewWindow, qui empêche les popups, alors c'est pris en charge.

Quelqu'un a-t-il déjà utilisé l'une de ces méthodes et bloqué avec succès tous les dialogues, erreurs de script, etc.?

MODIFIER

Ce n'est pas une instance autonome d'IE, mais une instance d'un contrôle WebBrowser vivant sur une application Windows Form. Quelqu'un a-t-il déjà utilisé ce contrôle, ou le contrôle sous-jacent, AxSHDocVW ?

EDIT à nouveau

Désolé d'avoir oublié de mentionner cela ... J'essaie de bloquer une alerte JavaScript () , avec juste un bouton OK. Peut-être que je peux transtyper un objet IHTMLDocument2 et accéder aux scripts de cette façon, j'ai un peu utilisé MSHTML, tout le monde le sait?

Était-ce utile?

La solution

C’est définitivement du hacky, mais si vous travaillez avec le contrôle WebBrowser, vous vous retrouverez à faire beaucoup de choses sur le hacky.

C’est la façon la plus simple que je connaisse de le faire. Vous devez injecter du JavaScript pour remplacer la fonction d'alerte ... dans le sens de l'injection de cette fonction JavaScript:

window.alert = function () { }

Il existe de nombreuses façons de le faire , mais il est très possible de le faire. Une possibilité consiste à connecter une implémentation de l'interface DWebBrowserEvents2 . Une fois que cela est fait, vous pouvez ensuite vous connecter à NavigateComplete, à DownloadComplete ou à DocumentComplete (ou à une variante de celui-ci), puis appeler une méthode InjectJavaScript que vous avez implémentée qui effectue ce remplacement du paramètre window.alert. méthode.

Comme je l'ai dit, hacky, mais ça marche :))

Je peux entrer dans plus de détails si besoin est.

Autres conseils

Et pour un moyen facile d’injecter cette ligne magique de javascript, lisez comment injecter du Javascript dans le contrôle du navigateur Web .

Ou utilisez simplement ce code complet:

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

Vous devrez peut-être personnaliser certaines choses, consultez IDocHostUIHandler , puis vérifiez certaines des autres interfaces connexes. Vous pouvez avoir beaucoup de contrôle, même au point de personnaliser l'affichage de dialogue / ui (je ne me souviens plus de quelle interface le fait). Je suis presque sûr que vous pouvez faire ce que vous voulez, mais cela nécessite de bricoler dans les éléments internes de MSHTML et de pouvoir implémenter les différentes interfaces COM .

Quelques autres idées: http://msdn.microsoft.com/en-us/library/aa770041. aspx

IHostDialogHelper
IDocHostShowUI

C’est peut-être ce que vous envisagez de mettre en œuvre.

Bloqueur d'alerte à l'épreuve des balles:

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

Cet exemple suppose que la référence Microsoft.mshtml ait été ajoutée, " à l'aide de mshtml; " dans vos espaces de noms et Navigateur est votre instance WebBrowser .

Pourquoi est-il pare-balles? Premièrement, il gère les scripts dans les cadres . Ensuite, il ne se bloque pas lorsqu'un "killer frame" spécial existe dans le document. Un "killer frame" est un cadre qui soulève une exception lors de la tentative d'utilisation en tant qu'objet HtmlWindow. Tout "foreach" utilisé sur Document.Window.Frames provoquerait une exception, donc plus sûr "pour" et "; La boucle doit être utilisée avec le bloc try / catch.

Ce n'est peut-être pas le code le plus lisible, mais il fonctionne avec des pages réelles et mal formées.

webBrowser1.ScriptErrorsSuppressed = true;

Ajoutez simplement cela à votre fonction de niveau d’entrée. Après beaucoup de recherches, c’est quand j’ai découvert cette méthode et que je touche au bois jusqu’à présent, c’est son travail. A la vôtre !!

window.showModelessDialog et window.showModalDialog peuvent être bloqués en implémentant l'interface INewWindowManager. De plus, le code ci-dessous montre comment bloquer les dialogues d'alerte en implémentant 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;
    }
}

Je viens de publier un article sur Code Project qui pourrait vous aider.

Veuillez consulter - http://www.codeproject.com/KB/shell/ WebBrowserControlDialogs.aspx

J'espère que cela vous aidera.

Le InjectAlertBlocker est absolument correct le code est

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

Les références à ajouter sont

  1. Ajoutez une référence à MSHTML , qui sera probablement appelée " Bibliothèque d'objets HTML Microsoft" " sous COM références.

  2. Ajoutez à l'aide de mshtml; à vos espaces de noms.

  3. Obtenez une référence au IHTMLElement de votre élément de script:

Vous pouvez ensuite utiliser l'événement Navigated du navigateur Web en tant que:

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

Essayez-vous de mettre en place un robot Web? J'ai peu d'expérience dans l'utilisation du contrôle IE hébergé, mais j'ai réalisé quelques projets Win32 qui tentaient d'utiliser le contrôle IE. La désactivation des fenêtres contextuelles doit être effectuée via les gestionnaires d’événements du contrôle comme vous l’avez déjà fait, mais j’ai également constaté que vous deviez également modifier le paramètre 'Désactiver le débogage de script xxxx' dans les options d’IE (ou vous pouvez modifier le registre dans vos codes) en tant que Cjheath a déjà souligné. Cependant, j'ai également constaté que des étapes supplémentaires devaient être effectuées pour vérifier le contenu téléchargeable dans l'URL afin d'empêcher ces dialogues d'ouverture / enregistrement. Mais je ne sais pas comment traiter les fichiers en streaming car je ne peux pas les ignorer en regardant uniquement les URL. Finalement, je me suis tourné vers la bibliothèque Indy pour me sauver de tous les problèmes liés au traitement de IE. Enfin, je me souviens que Microsoft avait mentionné quelque chose en ligne que IE n’était pas conçu pour être utilisé comme contrôle OLE. Selon ma propre expérience, chaque fois que le contrôle accède à une nouvelle page, des fuites de mémoire sont apparues pour les programmes!

J'ai eu de gros problèmes avec ceci: charger une page Web destinée à l'impression et afficher une boîte de dialogue d'impression agaçante. InjectBlocker était le seul moyen qui fonctionnait, mais relativement peu fiable. Sous certaines conditions (je considère que le contrôle WebBrowser utilise le moteur IE et que cela dépend de la version installée d'IE), la boîte de dialogue Imprimer apparaît toujours. Il s’agit d’un problème majeur. La solution fonctionne sous Win7 avec IE9 installé, mais WinXP avec IE8 affiche la boîte de dialogue, quoi qu’il en soit.

Je pense que la solution consiste à modifier le code source et à supprimer le code javascript à imprimer avant que le contrôle ne rende la page. Cependant, j'ai essayé avec la propriété: DocumentText du contrôle Webbrowser et cela ne fonctionne pas. La propriété n’est pas en lecture seule, mais elle n’a aucun effet lorsque je modifie la source.

La solution que j'ai trouvée pour mon problème est le script Exec:

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

J'ai réussi à injecter le code ci-dessus en créant une classe WebBroswer étendue et en remplaçant la méthode OnNavigated .

Cela semblait bien fonctionner:

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

Simplement à partir des propriétés du contrôle du navigateur: scriptErrorSupressed = true

Le moyen le plus simple de procéder est: Dans le: contrôle Webbrowser vous avez la procédure (standard) BeforeScriptExecute

(Le paramètre pour BeforeScriptExecute est pdispwindow )

Ajouter ceci:

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

De cette manière, toute exécution de script sur l'alerte de fenêtre de page sera supprimée par le code injecté.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top