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

StackOverflow https://stackoverflow.com/questions/77659

Вопрос

У меня есть .NET 2.0 Элемент управления WebBrowser, используемый для навигации по некоторым страницам без взаимодействия с пользователем (не спрашивайте... длинная история).Из-за без пользователя характера этого приложения я установил свойство сценариста Webbrowser Control в True, которое документация, включенная в состояния VS 2005, [...] »скрывает все свои диалоговые окны, которые происходят от базового управления ActiveX, Не только ошибки сценариев ». А Статья MSDN однако об этом не упоминает.Мне удалось отменить событие NewWindow, которое предотвращает появление всплывающих окон, так что об этом позаботились.

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

РЕДАКТИРОВАТЬ

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

РЕДАКТИРОВАТЬ еще раз

Извините, я забыл об этом упомянуть...Я пытаюсь заблокировать Оповещение JavaScript(), с помощью кнопки ОК.Может быть, я могу преобразовать объект IHTMLDocument2 и таким образом получить доступ к сценариям. Я немного использовал MSHTML, кто-нибудь знает?

Это было полезно?

Решение

Это определенно хакерский подход, но если вы поработаете с элементом управления WebBrowser, вы обнаружите, что делаете много хакерских вещей.

Это самый простой способ, который я знаю, чтобы сделать это.Вам необходимо внедрить JavaScript, чтобы переопределить функцию оповещения...что-то вроде внедрения этой функции JavaScript:

window.alert = function () { }

Есть много способов сделать это, но это вполне возможно сделать.Одна из возможностей — подключить реализацию DWebBrowserEvents2 интерфейс.Как только это будет сделано, вы можете подключиться к NavigateComplete, DownloadComplete или DocumentComplete (или, как мы, к некоторым их вариантам), а затем вызвать реализованный вами метод InjectJavaScript, который выполняет это переопределение window.alert. метод.

Как я уже сказал, хакерски, но это работает :)

Я могу рассказать подробнее, если мне нужно.

Другие советы

А чтобы узнать о простом способе внедрения этой волшебной строки 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);
}

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

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

IHostDialogHelper
IDocHostShowUI

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

Пуленепробиваемый блокировщик оповещений:

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 добавлена ​​ссылка"использование MSHTML;" в ваших пространствах имен и Браузер это твой Веб-браузер пример.

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

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

webBrowser1.ScriptErrorsSuppressed = true;

Просто добавьте это в свою функцию начального уровня.После долгих исследований я наткнулся на этот метод и до сих пор трогаю дерево, и он работает.Ваше здоровье!!

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

Я только что опубликовал статью о Code Project, которая может вам помочь.

Пожалуйста, посмотри - http://www.codeproject.com/KB/shell/WebBrowserControlDialogs.aspx

Надеюсь это поможет.

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

Вы пытаетесь реализовать веб-робота?У меня мало опыта в использовании размещенного элемента управления IE, но я выполнил несколько проектов Win32, пытаясь использовать элемент управления IE.Отключение всплывающих окон должно выполняться через обработчики событий элемента управления, как вы уже это сделали, но я обнаружил, что вам также необходимо изменить параметр «Отключить отладку сценариев xxxx» в параметрах IE (или вы можете изменить реестр в своих кодах), как Джейхит уже отметил.Однако я также обнаружил, что необходимо выполнить дополнительные шаги по проверке URL-адреса навигации на наличие любого загружаемого содержимого, чтобы предотвратить появление диалоговых окон открытия/сохранения.Но я не знаю, как быть с потоковыми файлами, так как я не могу их пропустить, просматривая только URL-адреса, и в конце концов я обратился к библиотеке Indy, избавившей меня от всех хлопот по работе с IE.Наконец, я помню, что Microsoft упомянула в Интернете, что IE не предназначен для использования в качестве элемента управления OLE.По моему собственному опыту, каждый раз, когда элемент управления переходит на новую страницу, в программах возникают утечки памяти!

У меня были большие проблемы с этим:загружается веб-страница, предназначенная для печати, и отображается раздражающее диалоговое окно «Печать».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" });

Мне удалось внедрить приведенный выше код, создав расширенный 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 );
  }
}

Просто из свойств элемента управления браузера:scriptErrorSupressed=истина

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

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

Добавь это :

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top