Блокировка диалогов в элементе управления .NET WebBrowser

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

У кого-нибудь есть опыт использования одного из них и успешной блокировки всех диалогов, ошибок сценария и т. Д.?

ИЗМЕНИТЬ

Это не отдельный экземпляр IE, а экземпляр элемента управления WebBrowser, находящийся в приложении Windows Form. У кого-нибудь есть опыт работы с этим элементом управления или лежащим в его основе, AxSHDocVW?

ИЗМЕНИТЬ еще раз

Извините, я забыл упомянуть об этом ... Я пытаюсь заблокировать предупреждение JavaScript () с помощью кнопки ОК. Может быть, я могу преобразовать объект 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 instance.

Почему он пуленепробиваемый? Во-первых, он обрабатывает скрипты внутри фреймов. Затем он не дает сбоев, если в документе есть специальный "фрейм-убийца". «Фрейм-убийца» - это фрейм, который вызывает исключение при попытке использовать его в качестве объекта HtmlWindow. Любой «foreach», используемый в Document.Window.Frames, вызовет исключение, поэтому более безопасный цикл «for» должен использоваться с блоком try / catch.

Может быть, это не самый читаемый фрагмент кода, но он работает с реальными, плохо сформированными страницами.

person Community    schedule 21.03.2012
comment
Я искал код, который выполняет итерацию по кадрам, чтобы перезаписать javascript предупреждения. Это был единственный метод, который я нашел для достижения своей цели. Спасибо. - person Jaime Marín; 13.08.2013

Возможно, вам придется настроить некоторые вещи, взглянуть на IDocHostUIHandler, а затем проверить некоторые другие связанные интерфейсы. Вы можете иметь достаточный контроль, даже до настройки отображения диалогового окна / пользовательского интерфейса (я не могу вспомнить, какой интерфейс это делает). Я почти уверен, что вы можете делать то, что хотите, но для этого нужно копаться во внутренностях MSHTML и иметь возможность реализовывать различные COM интерфейсы.

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

IHostDialogHelper
IDocHostShowUI

Это могут быть вещи, которые вы хотите реализовать.

person Jim Crafton    schedule 21.09.2008
comment
+1, но в любом случае реализация IHostDialogHelper и IDocHostShowUI не блокирует функции подтверждения и 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" под 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 элемента управления webbrowser, и он не работает. Свойство не доступно только для чтения, но оно не действует, когда я изменяю источник.

Решение, которое я нашел для своей проблемы, - это сценарий 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

Самый простой способ сделать это: В: Webbrowser Control у вас есть процедура (стандартная) BeforeScriptExecute

(Параметр для BeforeScriptExecute - pdispwindow)

Добавь это :

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

Таким образом, перед выполнением любого скрипта в окне страницы предупреждение будет подавлено внедренным кодом.

person Community    schedule 28.03.2016