Reputation: 41
I have an Excel VBA application which uses internetexplorer.application to explore an application. Starting around 2/21/15, this application started failing on readyState being stuck on 1 forever rather than ultimately migrating to 4. This only occurred when navigating the second (or further) link. The first URL works fine.
The machine with the problem is a Core i5 M520 CPU (4 CPU) running 64-bit Windows 7.
Another machine with a Core 2 Duo T9400 running 32-bit Windows 7 executes the code without a problem.
This feels like some sort of race condition but I am not sure if I have to do something special under 64-bit windows.
I am using Internet Explorer 11, Windows 7, and Excel 2003 (or 2013). Any idea on what is going wrong?
Option Explicit
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Dim objIE As Object
Dim iNodeCount As Long
Dim iLevel As Long
Dim iMaxLevel As Long
Dim iReadyStateLoopCount As Long
'------------------------------------------------------
'
' Main driver of the test case
'
'------------------------------------------------------
Sub Test_IE_Interface()
Set objIE = CreateObject("InternetExplorer.Application")
With objIE
.AddressBar = True
.StatusBar = True
.MenuBar = True
.Toolbar = True
.Visible = True
End With
LoadAPage "http://events.gotsport.com/events/Default.aspx?EventID=44163"
' This example generally hangs on the following call
LoadAPage "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=18"
LoadAPage "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=19"
LoadAPage "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=13"
LoadAPage "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=14"
LoadAPage "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=15"
LoadAPage "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=16"
LoadAPage "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=17"
objIE.Quit
End Sub
'--------------------------------------------------------------
'
' This routine loads a web page and then peruses the document
'
'--------------------------------------------------------------
Sub LoadAPage(sURL As String)
Dim sState As String
Dim sNewURL As String
Dim objDoc As Object
objIE.navigate sURL
Do While objIE.Busy
DoEvents
Sleep 10
DoEvents
Loop
' >>> Getting stuck in the following loop in the second call <<<
' >>> OBJie.readyState is always 1 (READYSTATE_LOADING) <<<
Do While objIE.readyState <> 4 ' READYSTATE_COMPLETE = 4
DoEvents
Sleep 10
DoEvents
iReadyStateLoopCount = iReadyStateLoopCount + 1
Loop
Set objDoc = objIE.document
sState = objDoc.readyState
Do While sState <> "complete"
DoEvents
Sleep 10
sState = objDoc.readyState
Loop
If objDoc.URL <> sURL Then
MsgBox "The new URL was not loaded" & vbCrLf & _
"URL Requested: " & sURL & vbCrLf & _
"URL Returned: " & objDoc.URL
End If
iNodeCount = 0
iLevel = 0
iMaxLevel = 0
PeruseTheDocument objDoc
End Sub
'--------------------------------------------------
'
' This is a dummy routine to examine the document
'
'--------------------------------------------------
Sub PeruseTheDocument(objNode As Object)
Dim objChild As Object
iNodeCount = iNodeCount + 1
iLevel = iLevel + 1
If iLevel > iMaxLevel Then
iMaxLevel = iLevel
End If
If Not objNode Is Nothing Then
If Not IsNull(objNode.FirstChild) Then
Set objChild = objNode.FirstChild
Do Until IsNull(objChild) Or objChild Is Nothing
' Make this go faster by not examining all nodes in the document
If iLevel < 5 Then
PeruseTheDocument objChild
End If
If IsNull(objChild.nextSibling) Then
Set objChild = Nothing
Else
Set objChild = objChild.nextSibling
End If
Loop
End If
End If
iLevel = iLevel - 1
End Sub
Upvotes: 0
Views: 3464
Reputation: 11
"Funny thing", sometimes the loop objIE.readyState <> 4
works, sometimes it doesn't and hangs with readyState = 1
(READYSTATE_LOADING
) even though the browser window is obviously finished loading.
It works best if I add a Sleep/DoEvents-loop (>500ms) after navigate
and before doing anything else with the IE-object:
objIE.navigate sURL
For i = 0 To 10
DoEvents
Sleep 100
Next i
objIE.Visible = True
Do While objIE.readyState <> 4
...
Hope that helps!
Upvotes: 1
Reputation: 11
(Geez this interface makes things hard!! I have to make this an answer, because it's too long for a comment.)
Your problem doesn't occur for me.
I don't have access to VBA, so I converted your code to VBScript. The difference is irrelevant to the issue at hand. Copy & paste my code into a file with .VBS extension. Double-click to run, and you'll see each page go ready in turn.
Note that VBScript variables are declared untyped, never eg. "As Object". I also made objIE local to procedure Test_IE_Interface(), then pass it explicitly to LoadAPage() - that's better design than using a global (but irrelevant to the problen at hand).
My conclusion is that either (1) you're inadvertantly not actually showing us the actual code that is actually running; or (2) there's something wrong with your network stack or internet connectivity. Personally I doubt it is (2).
Try my VBS code, see if it works, then convert it back to VBA and see what happens.
Option Explicit
Test_IE_Interface
WSCRIPT.QUIT
Sub Test_IE_Interface()
Dim objIE
Set objIE = CreateObject("InternetExplorer.Application")
With objIE
.AddressBar = True
.StatusBar = True
.MenuBar = True
.Toolbar = True ' is actually a numeric property, not boolean.
.Visible = True
End With
LoadAPage objIE, "http://events.gotsport.com/events/Default.aspx?EventID=44163"
LoadAPage objIE, "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=18"
LoadAPage objIE, "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=19"
LoadAPage objIE, "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=13"
LoadAPage objIE, "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=14"
LoadAPage objIE, "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=15"
LoadAPage objIE, "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=16"
LoadAPage objIE, "http://events.gotsport.com/events/schedule.aspx?EventID=44163&Gender=Boys&Age=17"
objIE.Quit
End Sub
Sub LoadAPage (objIE, sURL)
Dim objDoc
objIE.navigate sURL
Do While objIE.readyState <> 4
WSCRIPT.SLEEP 200 ' VBScript DOEVENTS/SLEEP for 0.2 seconds.
Loop
Set objDoc = objIE.document
MSGBOX "GOT " & SURL & vblf & vblf & left (objDoc.documentelement.outerhtml, 300)
End Sub
Upvotes: 0
Reputation: 11
I'd say all the next as a comment, but have no comment privilige.
(1) You say that it's stuck on readystate 1. Perhaps a silly question, but, how do you actually know that?
(2) It helps to disable irrelevent things when debugging. So comment-out the PeruseTheDocument call, and try again (on the off-chance that it's something to do with that procedure).
(3) Not the cause of your problem, but: while a document is loading, IE.BUSY is TRUE for most but not all of the time. It actually does go FALSE occasionally before the document has fully loaded. So waiting on IE.BUSY=FALSE is generally not correct. In your case that won't make any difference, because then you wait for readystate 4. But I'd remove the BUSY check, since it serves absolutely no purpose whatever, and it's based on a misunderstanding of what that property actually means.
HTH
Upvotes: 0