检测 WebBrowser 完整页面加载

Posted

技术标签:

【中文标题】检测 WebBrowser 完整页面加载【英文标题】:Detect WebBrowser complete page loading 【发布时间】:2011-02-16 04:46:26 【问题描述】:

如何检测 System.Windows.Forms.WebBrowser 控件何时完成加载?

我尝试使用 Navigate 和 DocumentCompleted 事件,但在文档加载期间它们都被引发了几次!

【问题讨论】:

你是如何使用 c# 的?这是一个 asp.net 问题,还是您使用的是网络浏览器控件? @kibibu 我正在使用 WebBrowser 控件。 如果页面有很多框架,比较 AbsolutePath 可能不起作用。我以前尝试过这种方法,但还没有成功。我仍然坚持这个问题。 :( :( 【参考方案1】:

我认为DocumentCompleted 事件也会被所有加载的子文档触发(例如 JS 和 CSS)。您可以查看DocumentCompleted 中的WebBrowserDocumentCompletedEventArgs 并检查Url 属性并将其与主页的Url 进行比较。

【讨论】:

这就是我自己解决这个问题后得出的结论。我在广告横幅之类的东西上得到了一堆额外的完成。我丢弃任何与我所关注的 URL 不匹配的事件,并且它有效。 @Loren Pechtel 我不敢说这种方法存在 3 个问题。首先,当您的父(***)url 进行服务器端 url 重定向时,您尝试比较的文档的 url 会发生变化。其次,存在框架和父页面具有相同 url 的情况,这会改变其他参数(如referrer 等)的行为,因此 url 是相同的。此外,客户端重定向 - 它们发生在您认为页面已加载并且 webbrowser 控件返回“一切顺利”之后。如果您需要有关如何减少这些问题的帮助,请告诉我,我可以在这里提供答案。 @Paul Kearney - pk 随时阅读我对 Loren 的最后评论。 从臀部射击 - 但我会在脚本不触发 documentloaded 上赌钱 - 因为它们没有“附加”DOMDocument。它可能是框架,因为包含框架集的 html 段在技术上具有嵌入在窗口中的窗口 - 因此是多个文档【参考方案2】:

我做了以下事情:

void BrowserDocumentCompleted(object sender,
        WebBrowserDocumentCompletedEventArgs e)

  if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath)
    return; 

  //The page is finished loading 

最后加载的页面往往是导航到的页面,所以这应该可以。

来自here。

【讨论】:

完美——正是我所需要的。解释为什么有时显示整个页面,有时只显示部分页面。 改成 ((WebBrowser)sender).Url ;-) 真的没用。问题是有facebook和twitter内容,主要问题是页面是否通过js和ajax加载内容。 documentReady 事件中的所有内容。 怎么称呼?我试着叫它BrowserDocumentCompleted(sender, e); @vanloc 名称无关紧要。您只需将其分配给 WebBrowser 控件的 DocumentCompleted 事件即可。【参考方案3】:

以下应该可以工作。

private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

    //Check if page is fully loaded or not
    if (this.webBrowser1.ReadyState != WebBrowserReadyState.Complete)
        return;
    else
        //Action to be taken on page loading completion

【讨论】:

非常有用且简单! 在我的应用程序中,该事件至少被触发了四次 @JackGriffin 那是因为每个 iframe 也是一个文档,因此会触发该事件。这样做很棘手。您可以按照 Paul 在上面的答案中提到的那样检查 Urls,但这也可能会失败,如 Erx_VB.NExT.Coder 所述。如果要打开的 URL 属于某个预定义的 URL 集,您可能知道如何避免这些。例如,当我第一次遇到这个问题时,我知道会打开哪些 URL,所以我创建了一个 WebBrowser 类的子类并向它添加了一些附加信息。然后,很容易(通过提示发送者对象)这样做。 @Transcendental 我看到了问题所在。凯尔的解决方案对我有用,但也许我只是幸运 :-)。 我也是。我的应用每两次触发一次。【参考方案4】:

请注意,由于服务器传输或 url 规范化,DocumentCompleted 中的 url 可能与导航 url 不同(例如,您导航到 www.microsoft.com 并在 documentcomplete 中获得 http://www.microsoft.com)

在没有框架的页面中,加载完成后会触发一次此事件。在具有多个框架的页面中,每个导航框架都会触发此事件(注意在框架内支持导航,例如单击框架中的链接可以将框架导航到另一个页面)。***别的导航框架(可能是也可能不是***浏览器)触发最终的 DocumentComplete 事件。

在本机代码中,您可以使用compare the sender of the DocumentComplete event to determine if the event is the final event in the navigation or not。但是在 Windows 窗体中,sender 参数不被 WebBrowserDocumentCompletedEventArgs 包装。您可以通过sink the native event 获取参数的值,也可以在 DocumentCompleted 事件处理程序中检查readystate property of the browser 或frame documents 以查看所有帧是否都处于就绪状态。

readystate 方法存在问题,好像存在download manager 并且导航到可下载文件,下载管理器可能会取消导航并且readystate 不会完成。

【讨论】:

【参考方案5】:

我遇到了多个DocumentCompleted 触发事件的相同问题,并尝试了上述所有建议。最后,似乎在我的情况下IsBusy 属性和Url 属性都不能正常工作,但ReadyState 似乎是我需要的,因为它在加载多个帧时具有“交互”状态并且它获得了状态仅在加载最后一个后才“完成”。因此,我知道页面何时完全加载了所有组件。

我希望这也可以帮助其他人:)

【讨论】:

【参考方案6】:

它似乎不会触发外部 javascript 或 CSS 文件的 DocumentCompleted/Navigated 事件,但它会触发 iframe。正如 PK 所说,比较 WebBrowserDocumentCompletedEventArgs.Url 属性(我还没有业力发表评论)。

【讨论】:

【参考方案7】:

如果您使用的是 WPF,则有一个 LoadCompleted 事件。

如果是Windows.FormsDocumentCompleted 事件应该是正确的。如果您正在加载的页面有框架,您的WebBrowser 控件将为每个框架触发DocumentCompleted 事件(有关详细信息,请参阅here)。我建议在每次触发事件时检查IsBusy 属性,如果它为假,则您的页面已完全加载完毕。

【讨论】:

【参考方案8】:

对具有多个嵌套框架的页面使用 DocumentCompleted 事件对我不起作用。

我使用 Interop.SHDocVW 库来转换 WebBrowser 控件,如下所示:

public class webControlWrapper

    private bool _complete;
    private WebBrowser _webBrowserControl;

    public webControlWrapper(WebBrowser webBrowserControl)
    
        _webBrowserControl = webBrowserControl;
    

    public void NavigateAndWaitForComplete(string url)
    
        _complete = false;

        _webBrowserControl.Navigate(url);

        var webBrowser = (SHDocVw.WebBrowser) _webBrowserControl.ActiveXInstance;

        if (webBrowser != null)
            webBrowser.DocumentComplete += WebControl_DocumentComplete;

        //Wait until page is complete
        while (!_complete)
        
            Application.DoEvents();
        
    

    private void WebControl_DocumentComplete(object pDisp, ref object URL)
    
        // Test if it's the main frame who called the event.
        if (pDisp == _webBrowserControl.ActiveXInstance)
            _complete = true;
    

当使用 webBrowserControl.Navigate(url) 方法导航到定义的 URL 时,此代码适用于我,但我不知道如何在使用 htmlElement.InvokeMember("click" )。

【讨论】:

【参考方案9】:

您可以使用事件 ProgressChanged ;最后一次提出将表明文档已完全呈现:

this.webBrowser.ProgressChanged += new
WebBrowserProgressChangedEventHandler(webBrowser_ProgressChanged);

【讨论】:

你怎么知道最后一次调用是什么时候?

以上是关于检测 WebBrowser 完整页面加载的主要内容,如果未能解决你的问题,请参考以下文章

WPF中WebBrowser 如何在页面加载的时候注入js脚本

C# webbrowser判断页面是否加载完毕

wpf webBrowser 禁用超链接

单击按钮后等待加载页面

如何检测 WebBrowser 控件中的 Javascript 执行

单击 WebBrowser 控件内的 HTML 链接