Блокиране на диалогови прозорци в контрола на .NET WebBrowser

Имам контрола .NET 2.0 WebBrowser, използвана за навигация в някои страници без потребителско взаимодействие (не питайте...дълга история). Поради липсата на потребителски характер на това приложение, зададох свойството ScriptErrorsSuppressed на контролата WebBrowser на true, което в документацията, включена към VS 2005, гласи, че [...] ще скрие всички негови диалогови прозорци, които произхождат от основната ActiveX контрола, не само грешки в скрипта." статията на MSDN обаче не споменава това. Успях да анулирам събитието NewWindow, което предотвратява изскачащите прозорци, така че това е решено.

Някой има ли опит с използването на някое от тези и успешното блокиране на всички диалогови прозорци, грешки в скрипта и т.н.?

РЕДАКТИРАНЕ

Това не е самостоятелен екземпляр на IE, а екземпляр на контрола на WebBrowser, живееща в приложение на Windows Form. Някой има ли опит с тази контрола или основната, AxSHDocVW?

РЕДАКТИРАНЕ отново

Съжалявам, че забравих да спомена това... Опитвам се да блокирам JavaScript alert() само с бутон OK. Може би мога да прехвърлям в обект IHTMLDocument2 и да получа достъп до скриптовете по този начин, използвал съм MSHTML малко, някой знае ли?


person Community    schedule 16.09.2008    source източник
comment
Вижте stackoverflow.com/questions/2476360   -  person BlueRaja - Danny Pflughoeft    schedule 16.12.2013


Отговори (12)


Това определено е хакерско, но ако работите с контролата на WebBrowser, ще откриете, че правите много хакерски неща.

Това е най-лесният начин, за който знам да направя това. Трябва да инжектирате JavaScript, за да замените функцията за предупреждение... нещо подобно на инжектиране на тази JavaScript функция:

window.alert = function () { }

Има много начини да направите това, но е много възможно да се направи. Една от възможностите е да се закачи реализация на интерфейса DWebBrowserEvents2. След като това стане, можете да включите NavigateComplete, DownloadComplete или DocumentComplete (или, както правим ние, някакъв техен вариант) и след това да извикате InjectJavaScript метод, който сте внедрили, който изпълнява това заместване на window.alert метод.

Както казах, хак, но работи :)

Мога да навляза в повече подробности, ако трябва.

person David Mohundro    schedule 19.09.2008

А за лесен начин да инжектирате този вълшебен ред от javascript, прочетете как да инжектирайте javascript в контрола на уеб браузъра.

Или просто използвайте този пълен код:

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);
}
person Community    schedule 30.10.2008
comment
Поправена е правописната грешка (element-›scriptEl) - person Sire; 30.07.2014

Бронеустойчив блокер за предупреждения:

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

Тази проба предполага, че сте добавили препратка към Microsoft.mshtml, „using mshtml;“ във вашите пространства от имена и Browser е вашият WebBrowser екземпляр.

Защо е брониран? Първо, той обработва скриптове в рамки. След това не се срива, когато в документа съществува специална "убиваща рамка". "Килър фрейм" е фрейм, който създава изключение при опит да се използва като HtmlWindow обект. Всеки "foreach", използван на Document.Window.Frames, би причинил изключение, така че трябва да се използва по-безопасен цикъл "for" с блок try/catch.

Може би това не е най-четимата част от кода, но работи с реални, неправилно оформени страници.

person Community    schedule 21.03.2012
comment
Търсих код, който итерира кадрите, за да презапише предупредителния javascript. Това беше единственият метод, който открих, за да постигна целта си. Благодаря. - person Jaime Marín; 13.08.2013

Може да се наложи да персонализирате някои неща, да разгледате IDocHostUIHandler и след това да проверите някои от другите свързани интерфейси. Можете да имате доста голям контрол, дори до точката на персонализиране на диалоговия дисплей/ui (не мога да си спомня кой интерфейс прави това). Почти съм сигурен, че можете да правите каквото искате, но това изисква бъркане във вътрешността на MSHTML и възможност за внедряване на различните COM интерфейси.

Някои други идеи: http://msdn.microsoft.com/en-us/library/aa770041.aspx

IHostDialogHelper
IDocHostShowUI

Това може да са нещата, които искате да внедрите.

person Jim Crafton    schedule 21.09.2008
comment
+1, но така или иначе внедряването на IHostDialogHelper и IDocHostShowUI не блокира функциите „confirm“ и „showModelessDialog“ - person walter; 27.01.2013

webBrowser1.ScriptErrorsSuppressed = true;

Просто добавете това към вашата функция за начално ниво. След много проучвания се натъкнах на този метод и докосване на дърво досега работи. Наздраве!!

person Community    schedule 26.10.2011

window.showModelessDialog и window.showModalDialog могат да бъдат блокирани чрез внедряване на интерфейс INewWindowManager, освен това кодът по-долу показва как да блокирате предупредителни диалози чрез внедряване на 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;
    }
}
person Community    schedule 03.02.2013

Кодът InjectAlertBlocker е абсолютно правилен

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

Референциите, които трябва да бъдат добавени, е

  1. Добавете препратка към MSHTML, която вероятно ще се нарича „Microsoft HTML Object Library“ под COM препратки.

  2. Добавете using mshtml; към вашите пространства от имена.

  3. Получете препратка към IHTMLElement на вашия скриптов елемент:

След това можете да използвате събитието Navigated на уеб браузъра като:

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();
}
person Community    schedule 25.04.2011

Опитвате ли се да внедрите уеб робот? Имам малко опит в използването на хостваната IE контрола, но завърших няколко Win32 проекта, опитвайки се да използвам IE контролата. Деактивирането на изскачащите прозорци трябва да се извърши чрез манипулаторите на събития на контролата, както вече направихте, но открих, че също трябва да промените „Деактивиране на отстраняването на грешки в скрипта xxxx“ в опциите на IE (или можете да промените системния регистър във вашите кодове) като cjheath вече посочи. Въпреки това открих също, че трябва да се направят допълнителни стъпки за проверка на URL адреса за навигация за всяко съдържание за изтегляне, за да се предотвратят тези диалогови прозорци за отваряне/запазване. Но не знам как да се справя с поточните файлове, тъй като не мога да ги пропусна, като гледам само URL адресите и в крайна сметка се обърнах към библиотеката Indy, което ми спести всички проблеми при работа с IE. И накрая, спомням си, че Microsoft спомена нещо онлайн, че IE не е проектиран да се използва като OLE контрола. Според моя собствен опит, всеки път, когато контролата навигира към нова страница, е внасяла течове на памет за програмите!

person William    schedule 19.09.2008

Имах по-големи проблеми с това: зареждане на уеб страница, която е предназначена за печат, и показва досаден диалогов прозорец за печат. InjectBlocker беше единственият начин, който работеше, но доста ненадежден. При определени условия (смятам, че се дължи на това, че контролът на WebBrowser използва IE двигател и това зависи от инсталираната версия на IE) диалоговият прозорец за печат все още се появява. Това е основен проблем, решението работи на Win7 с инсталиран IE9, но WinXP с IE8 показва диалоговия прозорец, независимо от всичко.

Вярвам, че решението е в модифициране на изходния код и премахване на javascript за печат, преди контролът да изобрази страницата. Въпреки това опитах това със: свойство DocumentText на контролата на уеб браузъра и не работи. Свойството не е само за четене, но няма ефект, когато променя източника.

Решението, което намерих за моя проблем, е скриптът Exec:

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

Успях да инжектирам кода по-горе, като създадох разширен клас WebBroswer и замених метода OnNavigated.

Това изглежда работи доста добре:

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 );
  }
}
person Community    schedule 01.12.2008

Просто от свойствата на контрола на браузъра: scriptErrorSupressed=true

person Community    schedule 27.01.2016

Най-лесният начин да направите това е: В: Контрол на уеббраузър имате процедурата (стандартна) BeforeScriptExecute

(Параметърът за BeforeScriptExecute е pdispwindow )

Добави Това :

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

По този начин преди всяко изпълнение на скрипт в прозореца на страницата предупреждението ще бъде потиснато от инжектиран код.

person Community    schedule 28.03.2016