Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can powershell wait until IE is DOM ready?

I'm currently writing a script and I'm using

while($IE.busy) {Start-Sleep 1}

to wait for the page to be ready.

Once the page is ready my script fills out and submits a form. I've been running into problems because (I think) IE reports that it's done when the page is loaded but before the document has been rendered (which causes the script to error out). My current workaround is to add a 4 second wait time after the page loads but I'd feel more comfortable with a method that isn't time based if possible.

like image 801
George Kendros Avatar asked Mar 19 '14 15:03

George Kendros


2 Answers

Here's how I do this.

Step 1 - Identify a web page element that only appears once the page is fully rendered. I did this using the Chrome developer tools 'Elements' view which shows the DOM view.

Step 2 - Establish a wait loop in the script which polls for the existence of the element or the value of text inside that element.

# Element ID to check for in DOM
$elementID = "systemmessage"

# Text to match in elemend
$elementMatchText = "logged in"

# Timeout
$timeoutMilliseconds = 5000

$ie = New-Object -ComObject "InternetExplorer.Application"

# optional
$ie.Visible = $true

$ie.Navigate2("http://somewebpage")
$timeStart = Get-Date
$exitFlag = $false

do {

    sleep -milliseconds 100

    if ( $ie.ReadyState -eq 4 ) {

        $elementText = (($ie.Document).getElementByID($elementID )).innerText
        $elementMatch = $elementText -match $elementMatchText

        if ( $elementMatch ) { $loadTime = (Get-Date).subtract($timeStart) }

    }

    $timeout = ((Get-Date).subtract($timeStart)).TotalMilliseconds -gt $timeoutMilliseconds
    $exitFlag = $elementMatch -or $timeout

} until ( $exitFlag )

Write-Host "Match element found: $elementMatch"
Write-Host "Timeout: $timeout"
Write-Host "Load Time: $loadTime"
like image 105
andyb Avatar answered Nov 18 '22 21:11

andyb


I found this thread really helpful and ended up coming up with a slightly different solution. I am pretty new to powershell so hopefully I didn't make a hash of it but this worked really well for me.

I used a "while" statement so that my condition would loop while true:

while($ie.document.body.outerHTML -notMatch "<input type=`"submit`" value=`"Continue`">") {start-sleep -m 100};

In this case I was matching against a portion of the "outerHTML" part of the body. As long as I don't match the specified text the script will wait and continue to loop the match check.

I like this solution as I could do it in more or less one line of code and I like to keep things compact where possible. Hopefully this is helpful to someone else. Like the OP I found ie.readystate to be very finnicky/unreliable but I really didn't want to just put a static sleep timer in.

Also, while Chrome is an excellent way to break a page down. You can also print to the console window once you have IE running programmatically by simply running:

$ie.document.body

You can dig through visually and then filter down to the section you want which should speed up your matching (I would guess), which is what I did in my code example above.

The only other thing I will note... I think -match uses "regex" because I had to use the tick mark (ex. ` ) to escape the quotes that were part of the string I was matching.

Cheers!

Here is a good reference on "while" logic: http://www.powershellpro.com/powershell-tutorial-introduction/logic-using-loops/

like image 29
Nathan Beam Avatar answered Nov 18 '22 21:11

Nathan Beam