Gematria
Gematria

Reputation: 105

VBS Foolproof way to check if site has loaded

I am having some issues with a script that loads a website. Basically, it sucks at detecting when the site is completely loaded, and it then starts doing errors because it cant find the designated objects.

Is there a way, instead of using ie.readystate or ie.busy, to check if site is completely loaded? Maybe by something like a loop that checks if the object is there, before Setting it?

Like:

For Each wnd In CreateObject("Shell.Application").Windows
  If InStr(1, wnd.FullName, "iexplore.exe", vbTextCompare) > 0 Then
    Set IE = wnd
    Exit For
  End If
 Next

IE.navigate2 "xxxx" 
 IE.Visible = 1   

Do Until IE.document.getElementByID("username").Value = "xxxx"

 Set Helem = IE.document.getElementByID("username") 
 Helem.Value = "xxxx"    
 Set Helem = IE.document.getElementByID("password")
 Helem.Value = "xxxx"   
 Set Helem = IE.document.forms("signupForm")
 Helem.Submit

Loop

ie.busy and ie.readystate (any combinaton) just seems very unstable when loading a form..

I could just use wscript.sleep to ensure the website is completely loaded, but that could be upwards of 10 seconds or more of wait between execution.

Any ideas? :)

Edit: As Requested:

One thing i have attempted, as someone claimed they had success doing that, is below:

Do while ie.readystate <> 4 wscript.sleep 200 Loop
Do while ie.busy wscript.sleep 200 Loop

Another is:

Do while ie.readystate <> 4 wscript.sleep 200 Loop
Do Until ie.readystate = 4 wscript.sleep 200 Loop

And ofcourse been trying them separately as well.

Issue is, once the site is flagged as loaded (readystate = 4) its not really 100% loaded. So when i try to do, for example:

 Set Helem = IE.document.getElementByID("username") 
Helem.Value = "xxxx" 

Then i will get an error because it couldnt find the object.

Upvotes: 1

Views: 7314

Answers (2)

Safwan
Safwan

Reputation: 360

The best method I was able to come up with so far is the code below. It relies on capturing the DocumentComplete event of Internet Explorer to detect when the page is fully loaded.

Features:

  • The script will wait for all elements to be loaded, including frames and sub-frames, before reporting that the page has loaded.
  • Avoids unnecessary delays waiting to check various properties like Busy and ReadyState using Sleep.
  • The LoadPage function has a timeout safety feature to prevent infinite looping, which can be adjusted.

Enjoy :)

Option Explicit

'Sub Main
'--------
 Dim DocumentComplete
 Dim objIE : Set objIE = WScript.CreateObject("InternetExplorer.Application", "IE_")
 objIE.Visible = True

 If LoadPage("https://stackoverflow.com") Then
    MsgBox "LoadPage completed."
 Else
    MsgBox "LoadPage timed out."
 End If

 Function LoadPage(ByVal strURL) 'As Boolean
'-------------------------------------------
 Const TimeOut = 10 'Seconds
 Dim StartTime : StartTime = Now()
 DocumentComplete = False
 objIE.Navigate strURL

 Do While Not DocumentComplete
    WScript.Sleep(1)
    If DateDiff("s", StartTime, Now()) > TimeOut Then
       LoadPage = False
       Exit Function
    End If
 Loop

 LoadPage = True

End Function 'LoadPage

 Sub IE_DocumentComplete(pDisp, URL)
'-----------------------------------
' Fires when a document is completely loaded and initialized.
' https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa768282(v=vs.85)

 If (pDisp Is objIE) Then
    DocumentComplete = True
 End If

End Sub 'IE_DocumentComplete

Upvotes: 0

Tmdean
Tmdean

Reputation: 9299

In my experience, there are 3 ready states that you need to check.

  1. The InternetExplorer object (ie.ReadyState = 4)
  2. The document readystate (ie.document.readyState = "complete")

and for it to be completely foolproof:

  1. The readystate of the document frames (if the page has frames, and this might need to be a recursive check)

Here's a VBScript adaptation of a VBA sub that I've used for this task.

' web page load timeout in 10ths of a second
Const WAIT_TIMEOUT = 300
Const ERR_TIMEOUT = 1000
Const READYSTATE_COMPLETE = 4

Sub WaitUntilLoaded(ie)
    Dim i, j, ready

    ' wait for page to connect
    i = 0
    Do Until ie.readyState = READYSTATE_COMPLETE
        WScript.Sleep 100
        i = i + 1
        If i > WAIT_TIMEOUT Then
            Err.Raise ERR_TIMEOUT, , "Timeout"
        End If
    Loop

    ' wait for document to load
    Do Until ie.document.readyState = "complete"
        WScript.Sleep 100
        i = i + 1
        If i > WAIT_TIMEOUT Then
            Err.Raise ERR_TIMEOUT, , "Timeout"
        End If
    Loop

    ' wait for frames to load
    Do
        ready = True
        For j = 0 To ie.document.frames.Length - 1
            If ie.document.frames(j).document.readyState <> "complete" Then
                ready = False
                WScript.Sleep 100
                i = i + 1
                If i > WAIT_TIMEOUT Then
                    Err.Raise ERR_TIMEOUT, , "Timeout"
                End If
            End If
        Next
    Loop Until ready
End Sub

Upvotes: 2

Related Questions