如何等到 WebBrowser 在 VB.NET 中完全加载?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3275515/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to wait until WebBrowser is completely loaded in VB.NET?
提问by Shubham
I am using the WebBrowser control in my VB.NET application to load a few URLs ( ~10-15) and save their HTML source in a text file. However, my code doesn't write the source of the current page rather the initial one because the it is triggered even before the page is loaded.
我在我的 VB.NET 应用程序中使用 WebBrowser 控件来加载几个 URL(~10-15)并将它们的 HTML 源保存在一个文本文件中。但是,我的代码没有编写当前页面的源代码,而是初始页面的源代码,因为它甚至在页面加载之前就被触发了。
How can I wait until the page is completely loaded before calling any event?
如何在调用任何事件之前等待页面完全加载?
I tried the following code but it doesn't work.
我尝试了以下代码,但它不起作用。
Do Until WebBrowser1.ReadyState = WebBrowserReadyState.Complete
Application.DoEvents()
Loop
采纳答案by Dan F
Sounds like you want to catch the DocumentCompletedevent of your webbrowser control.
听起来您想捕获webbrowser 控件的DocumentCompleted事件。
MSDN has a couple of good articles about the webbrowser control - WebBrowser Classhas lots of examples, and How to: Add Web Browser Capabilities to a Windows Forms Application
MSDN 有几篇关于 webbrowser 控件的好文章 - WebBrowser Class有很多示例,以及How to: Add Web Browser Capabilities to a Windows Forms Application
回答by bgmCoder
Salvete! I needed, simply, a function I could call to make the code wait for the page to load before it continued.After scouring the web for answers, and fiddling around for several hours, I came up with this to solve for myself, the exact dilemma you present. I know I am late in the game with an answer, but I wish to post this for anyone else who comes along.
萨尔维特!简单地说,我需要一个可以调用的函数,使代码在继续之前等待页面加载。在网上搜索答案并摆弄了几个小时后,我想出了这个来为自己解决,即您提出的确切困境。我知道我在游戏中迟到了答案,但我希望将其发布给其他任何人。
usage:just call WaitForPageLoad()
just after a call to navigation:
用法:只需WaitForPageLoad()
在调用导航后调用:
whatbrowser.Navigate("http://www.google.com")
WaitForPageLoad()
another examplewe don't combine the navigate feature with the page load, because sometimes you need to wait for a load without also navigating, for example, you might need to wait for a page to load that was started with an invokemember
event:
另一个例子我们没有将导航功能与页面加载结合起来,因为有时您需要等待加载而不进行导航,例如,您可能需要等待以invokemember
事件启动的页面加载:
whatbrowser.Document.GetElementById("UserName").InnerText = whatusername
whatbrowser.Document.GetElementById("Password").InnerText = whatpassword
whatbrowser.Document.GetElementById("LoginButton").InvokeMember("click")
WaitForPageLoad()
Here is the code:You need both subs plus the accessible variable, pageready
.
First, make sure to fix the variable called whatbrowser
to be your webbrowser control
这是代码:您需要 subs 和可访问变量,pageready
. 首先,确保修复称为whatbrowser
您的网络浏览器控件的变量
Now, somewhere in your module or class, place this:
现在,在你的模块或类中的某个地方,放置这个:
Private Property pageready As Boolean = False
#Region "Page Loading Functions"
Private Sub WaitForPageLoad()
AddHandler whatbrowser.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
While Not pageready
Application.DoEvents()
End While
pageready = False
End Sub
Private Sub PageWaiter(ByVal sender As Object, ByVal e As WebBrowserDocumentCompletedEventArgs)
If whatbrowser.ReadyState = WebBrowserReadyState.Complete Then
pageready = True
RemoveHandler whatbrowser.DocumentCompleted, New WebBrowserDocumentCompletedEventHandler(AddressOf PageWaiter)
End If
End Sub
#End Region
回答by david marcus
Technically, there are two issues with the code posted by BGM:
从技术上讲,BGM发布的代码存在两个问题:
the adding of the handlers in the WaitForPageLoad method is potentially too late. The navigation is initiated before the handlers are added which means that in very rare cases where the browser already has the page it may complete before the handlers are added in which case you will miss the event and sit forever waiting.
The solution is to add the handlers before the navigation starts and remove them after the navigation completed
This means the WaitForPageLoad method needs to be split into two methods. One is called before initiating the navigation. It should set the handlers. The second part does the ReadyState monitoring and cleans up when 'Ready'.
good programming practices is to add a timeout so that a lost (or crashed, or looping) browser doesn't make your code wait forever for the document completed even
在 WaitForPageLoad 方法中添加处理程序可能为时已晚。导航在添加处理程序之前启动,这意味着在极少数情况下,浏览器已经拥有页面,它可能会在添加处理程序之前完成,在这种情况下,您将错过事件并永远等待。
解决方案是在导航开始之前添加处理程序并在导航完成后删除它们
这意味着 WaitForPageLoad 方法需要拆分为两个方法。在启动导航之前调用一个。它应该设置处理程序。第二部分执行 ReadyState 监控并在“就绪”时进行清理。
良好的编程实践是添加超时,以便丢失(或崩溃或循环)的浏览器不会让您的代码永远等待文档完成,即使
回答by Tronzeus
Sometimes if you use JavaScript the DocumentComplete
event don't return the right answer; I use the event ProgressChanged
instead:
有时,如果您使用 JavaScript,该DocumentComplete
事件不会返回正确的答案;我ProgressChanged
改为使用该事件:
Private Sub WebBrowser1_ProgressChanged(sender As Object, e As WebBrowserProgressChangedEventArgs) Handles WebBrowser1.ProgressChanged
Console.WriteLine("Current Progress: " + e.CurrentProgress.ToString)
If e.CurrentProgress = e.MaximumProgress Then
' The maximum progress is reached
load_started = True
End If
' The page is confirmed downloaded after the progress returns to 0
If e.CurrentProgress = 0 Then
If load_started Then
' The page is ready to print or download...
WebBrowser1.Print()
load_started = False
End If
End If
End Sub
回答by JCM
Hold on...
坚持,稍等...
From my experience, you SHOULD make sure that the DocumCompleted
belongs to YOUR URL and not to a frame sub-page, script, image, CSS, etc. And that is regardless of the IsBusy
or the ReadyState
is finished or not, which both are often inaccurate when page is slightly complex.
根据我的经验,您应该确保DocumCompleted
属于您的 URL,而不是属于框架子页面、脚本、图像、CSS 等。这与IsBusy
或ReadyState
完成与否无关,这两者在以下情况下通常都是不准确的页面略复杂。
Well, that is my own personal experience, on a working program of VB.2013 and IE11. Let me also mention that you should take into account also the compatibility mode IE7 which is ON by default at the webBrowser1
.
嗯,这是我个人的经验,在 VB.2013 和 IE11 的工作程序上。我还要提一下,您还应该考虑兼容模式 IE7,该模式在webBrowser1
.
' Page, sub-frame or resource was totally loaded.
Private Sub webBrowser1_DocumentCompleted(sender As Object, _
e As WebBrowserDocumentCompletedEventArgs) _
Handles webBrowser1.DocumentCompleted
' Check if finally the full page was loaded (inc. sub-frames, javascripts, etc)
If e.Url.ToString = webBrowser1.Url.ToString Then
' Only now you are sure!
fullyLoaded = True
End If
End Sub
回答by Landon Tyner
In the load events, use Me.Hide
.
在加载事件中,使用Me.Hide
.
In WebBrowser1.DocuementCompleted, use Me.Show
在 WebBrowser1.DocuementCompleted 中,使用 Me.Show
回答by J. Scott Elblein
Another option is to check if it's busy with a timer:
另一种选择是检查它是否正忙于计时器:
Set the timer as disabled by default. Then whenever navigating, enable it. i.e.:
将计时器设置为默认禁用。然后每当导航时,启用它。IE:
WebBrowser1.Navigate("https://www.somesite.com")
tmrBusy.Enabled = True
And the timer:
和计时器:
Private Sub tmrBusy_Tick(sender As Object, e As EventArgs) Handles tmrBusy.Tick
If WebBrowser1.IsBusy = True Then
Debug.WriteLine("WB Busy ...")
Else
Debug.WriteLine("WB Done.")
tmrBusy.Enabled = False
End If
End Sub
回答by Paul Blakeley
I struggled with this 'fully loaded' issue for some time but found the following solution worked for me. I'm using IE7, so I'm not sure if this works in other versions, but worth a look.
我在这个“满载”问题上挣扎了一段时间,但发现以下解决方案对我有用。我正在使用 IE7,所以我不确定这是否适用于其他版本,但值得一看。
I split the problem into two parts; first I needed a message from the DocumentComplete event;
我把问题分成两部分;首先,我需要来自 DocumentComplete 事件的消息;
Private Sub WebBrowser1_DocumentComplete(ByVal pDisp As Object, URL As Variant)
fullyLoaded = True
End Sub
Then in the part of code where I need to wait till the web page has fully loaded I call another sub that does this;
然后在我需要等待网页完全加载的代码部分中,我调用另一个执行此操作的子程序;
Private Sub holdBrowserPage()
fullyLoaded = False
Do While fullyLoaded = False
DoEvents
Loop
fullyLoaded = False
End Sub
In addition, I also needed to do the same thing whilst waiting for javascript code to complete. For instance on one page when you select an item from an html drop down list, it populated the next drop down list, but took a while to reveal itself. In that instance I found calling this;
此外,我还需要在等待 javascript 代码完成的同时做同样的事情。例如,在一个页面上,当您从 html 下拉列表中选择一个项目时,它会填充下一个下拉列表,但需要一段时间才能显示出来。在那种情况下,我发现调用它;
Private Sub holdBrowser()
Do While WebBrowser1.Busy Or WebBrowser1.ReadyState <> READYSTATE_COMPLETE
DoEvents
Loop
End Sub
was enough to hold the browser. Not sure if this will help everyone, as a combination of IE7, the website I was loading, and the javascript that the page was running alone might have allowed this solution, but certainly worth a try.
足以容纳浏览器。不确定这是否对每个人都有帮助,因为 IE7、我正在加载的网站以及页面单独运行的 javascript 的组合可能允许使用此解决方案,但当然值得一试。
回答by Maciej
I made similar function (only that works to me); sorry it is in C# but easy to translate...
我做了类似的功能(只对我有用);抱歉,它是在 C# 中,但很容易翻译...
private void WaitForPageLoad () {
while (pageReady == false)
Application.DoEvents();
while (webBrowser1.IsBusy || webBrowser1.ReadyState != WebBrowserReadyState.Complete)
Application.DoEvents();
}