如何在 WebBrowser 控件中正确显示当前和真实加载的 url?

How to properly display the current and real url loaded in a WebBrowser control?

在我的表单中,我添加了一个 WebBrowser 和一个 TextBox,我想在上面显示当前加载的 Url.

注意 Microsoft Docs 的内容:

触发事件的顺序是:NavigatingNavigatedDocumentCompleted ,所以我正在处理这些事件以尝试正确更新当前 url:

private void WebBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e) {
    this.TextBox1.Text = e.Url.ToString();
}

private void WebBrowser1_Navigated(object sender, WebBrowserNavigatedEventArgs e) {
    this.TextBox1.Text = e.Url.ToString();
}

private void WebBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) {
    this.TextBox1.Text = e.Url.ToString();
}

问题是由于某些原因 url 似乎没有为某些网站正确更新...

例如,在 Google 的搜索引擎中导航时,如果我点击 Google 图片按钮,url 会更新为“http://www.google.com/blank.html”。此外,我在 TextBox 中显示的 url 与我在 Firefox 或 Chrome 的地址栏中看到的 url 并不完全相同;出于某种原因,我获得的 urls 在查询中有额外的参数。

自己看:

https://i.imgur.com/PQlSu47.gif

是否有任何解决方法可以改善这种烦人的行为,以便我可以像 Firefox 或 Chrome 那样高效地显示当前 url?。我的意思是,例如 Firefox 和 Chrome 不会在地址栏中显示“http://www.google.com/blank.html”,也不会显示带有附加参数的 url 查询,因为我必须显示(您可以请参阅上面的 GIF 图片)。

请注意,Google 网站的问题仅作为示例。我要求一个通用的解决方案,因为这个问题出现在更多的网站上。


另请注意,如果我使用 CefSharp 的基于 chromium 的 Web 浏览器,而不是 WebBrowser 组件,则调整我的代码以重现与我对 display/update当前的url,那么问题就部分消失了...

使用 CefSharp 在浏览 Google 图像时不显示“http://www.google.com/blank.html”,但是 url 的查询仍然包含其他参数/​​与 urls 显示在 Firefox 或 Chrome 浏览器中。 除此之外,我想避免使用 CefSharp 来解决此类问题...

对于给定的 URL,可以多次触发 DocumentCompleted,因为一个页面可以包含同样触发该事件的 iframe。因此,我建议您仅在 NavigatingNavigated 事件中更新文本框。

TL;DR

而不是事件参数中的 URL,使用 Web 浏览器控件中的 URL:

string url = webBrowser1.Url.ToString();

长答案

您在这里缺少的是 HTML 页面可以包含 iframe elements. An iframe encapsulates HTML Window and the contained HTML Document,并且它执行自己的导航。 WebBrowser 控件的导航事件会触发顶部 window(您要为其显示 URL)和 iframe。你必须区分这两者。

具体来说,在您的情况下 http://www.google.com/blank.html 来自 iframe:

<html> <!-- top window -->
    <body> <!-- top window's document -->
        <iframe src="http://www.google.com/blank.html">
            <!-- 
            here the browser will load and "insert" HTML of blank.html
            lines below don't exist in the original HTML 
            they are loaded and "inserted" here by the browser 
            -->
            <html> <!-- iframe's window -->
                <body> <!-- iframe's window's document -->
                    <!-- the body can contain additional iframes... --> 
                </body>
            </html>
        </iframe>
    </body>
</html>

通常,HTML 页面的 DOM 是 HTML Window 对象的树,根 window 由 window.top 属性。根据页面的设计方式,iframe 可以显示或隐藏;它们可以由服务器在 HTML 中呈现,也可以在浏览器中通过 JavaScript:

动态地操作、创建或删除
  • 创建新的 iframe 时,它会导航到 src 属性中指定的 URL。如果既未指定 src 也未指定嵌入内容,则导航 URL 将为 about:blank.
  • 当现有 iframesrc 属性被修改时,iframe 将导航到新的 src.
  • window.location 修改了 top 或 iframe HTML Window 时,它将执行导航到新的 location.

然而,确定哪个 HTML Window(顶部或 iframe)执行导航似乎不是一件小事,因此更简单方法只是获得顶部 window:

的 URL
string url = webBrowser1.Url.ToString();

或在 DocumentCompleted 事件之后:

HtmlWindow topWindow = webBrowser1.Document.Window;
string url = topWindow.Url.ToString();