Jump to content
wisem2540

Help Improving my IE automation script

Recommended Posts

wisem2540

I am not a pro at all with IE automation.  I am hoping someone can help me make this better.

 1. In the first area of the script, I am assuming that I am going to get a cert mismatch error, still testing the getlink function to click CONTINUE.  The question is, how can I have it watch for this error rather than assuming it will appear?

2. In the second part of the script, I am returning the info for the LOGIN button.  Rather than using Sleep (1000), how can I have it wait until the LOGIN button is visible?

3.  In my functions, rather than looping through and waiting until name= and ID=, is there an easier way to target these directly, since I know what values I am waiting for?

 

Thanks

 

 

GUICtrlSetData($Label0, "Resetting Camera"); Set Label


$oIE = _IECreate("http://"&$IP,0,$showIE)
Sleep (1000)
Call ("getlink")
Local $link = _IEGetObjByName ($oie, $buttonid)
_IEAction($link, "click")
_IELoadWait ($oIE)

Sleep (1000)
Call ("getbutton","button")
Local $userfield = _IEGetObjByName($oie, "username")
Local $passwordfield = _IEGetObjByName($oie, "password")
Local $loginbutton = _IEGetObjByName ($oie, $buttonid)
_IEFormElementSetValue($userfield, $user)
_IEFormElementSetValue($passwordfield, $password)
_IEAction($loginbutton, "click")

Sleep (2000)
Call ("getbutton2")
Local $shutdownbutton = _IEGetObjByName ($oie, $buttonid)
_IEAction($shutdownbutton, "click")
_IELoadWait ($oIE)

Sleep (1000)
Local $userfield = _IEGetObjByName($oie, "shutdownusername")
Local $passwordfield = _IEGetObjByName($oie, "Shutdownpassword")
_IEFormElementSetValue($userfield, $user)
_IEFormElementSetValue($passwordfield, $password)

Call ("getbutton3")
Local $restartbutton = _IEGetObjByName ($oie, $buttonid)
_IEAction($restartbutton, "click")

_IEQuit ($oIE)
AdlibRegister ("Pingip"); start ping





Func getbutton($text)
$oInputs = _IETagNameGetCollection($oIE, $text)
For $oInput In $oInputs
$buttonid = $oInput.id
Next
EndFunc

Func getbutton2()
$oInputs = _IETagNameAllGetCollection($oIE)
For $oInput In $oInputs
$buttonid = $oInput.id
$buttonname = $oInput.tagname
$innertext = $oInput.innerText
 If $buttonname = "A" and StringInStr($innertext,"Shutdown") Then Return
Next
EndFunc


Func getbutton3()
$oInputs = _IETagNameAllGetCollection($oIE)
For $oInput In $oInputs
$buttonid = $oInput.id
$buttonname = $oInput.tagname
$innertext = $oInput.innerText
 If $buttonname = "button" and StringInStr($innertext,"Restart") Then Return
Next
EndFunc

Func getlink()
$oInputs = _IETagNameAllGetCollection($oIE)
For $oInput In $oInputs
$buttonid = $oInput.id
$buttonname = $oInput.tagname
$innertext = $oInput.innerText
MsgBox (0, $buttonid, $Buttonname)
;If $buttonname = "overridelink" Then Return
Next
EndFunc

 

Share this post


Link to post
Share on other sites
Danp2

Some general observations --

  • Never understood why people insist on using Call() in this fashion. Why not just do this?
    GetLink()
    GetButton("button")
    etc
  • Is there a reason you are using _IETagNameAllGetCollection instead of _IETagNameGetCollection, which would allow you to target specific types of elements?

  • Would help if you posted the associated HTML code so that we can get a better idea of what elements you are trying to access

Share this post


Link to post
Share on other sites
wisem2540

If I recall, I chose GETALLCOLLECTION because the IDs are dynamic and change all the time.  This was the only way I could get it to work.  But as I said, I am a novice as IE automation, which is why I am here.   Here is the code for the buttons I need to target.

This element I want to monitor for, and only click it if it appears

<a name="overridelink" id="overridelink" href="https://10.10.10.10/">Continue to this website (not recommended).</a>

 

This is the first login button and again the ID changes every time the page loads

<button class="Wt-btn" id="oi9c5qr" onclick="var e=event||window.event,o=this;if($(o).hasClass('Wt-disabled')){Wt3_2_3.cancelEvent(e);return;}Wt._p_.update(o,'s3bc',e,true);" type="button">
    Login
    </button>

 

This is the "shutdown button" on the next page

<a id="oi9c3pe" onclick="var e=event||window.event,o=this;if(e.ctrlKey||e.metaKey||(Wt3_2_3.button(e) > 1))return true;else{if($(o).hasClass('Wt-disabled')){Wt3_2_3.cancelEvent(e);return;}Wt3_2_3.cancelEvent(e,0x2);Wt._p_.update(o,'s4ae',e,true);}" href="/?_=/admin/shutdown"><span id="oi9c3pd" style="white-space: nowrap;">
    Shutdown
    </span></a>

and finally this is the restart button that restarts the camera

<button class="Wt-btn radio" id="oi9c3sl" onclick="var e=event||window.event,o=this;if($(o).hasClass('Wt-disabled')){Wt3_2_3.cancelEvent(e);return;}Wt._p_.update(o,'s4a3',e,true);" type="button">
    Restart
    </button>

 

Share this post


Link to post
Share on other sites
wisem2540

Here is a script provided by the vendor that shows how they targeted the elements with powershell.

<#***********************************************************************************************
*                                                                                               *
 Author: Brandon Moser                                                                          *
* Purpose: Reboot HD40 endpoints programmatically                                               *
* Date: 2016.02.29                                                                              *
* Version: 1.1                                                                                  *
************************************************************************************************#>


# Set variables (accepts input at command-line: -switch [val])**********************************
Param( 
    [string]$inputFile = ".\rebootLoopInput.txt",
    [string]$username = "user",
    [string]$password = "password",
    [ipAddress]$url = "0.0.0.0",
    [int]$timeoutMilliseconds = "10000"    
 )

 
# FUNCTIONS ***********************************************************************************

# Pause function; waits for IE comObject to finish loading current page. Conditional wait followed
# by hard wait to allow DOM to render. Hard wait not as elegant as checking for innerHtml load (TODO)
function loadWait() {

    while( $ie.ReadyState -ne 4 -or $ie.Busy ){Start-Sleep -m 100}
    Start-sleep -s 1
} # end of function loadWait()

# Wait for elementMatchText to show up in elementID or timeoutMilleseconds to elapse
function domWaitID($elementID, $elementMatchText) {
    $timeout = 0
    $timeStart = Get-Date
    do {

        while( $ie.ReadyState -ne 4 -or $ie.Busy ){Start-Sleep -m 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 )
}

# Wait for elementMatchText to show up in inner HTML
function domWaitHREF($elementMatchText) {
    $timeout = 0
    $timeStart = Get-Date
    do {

        while( $ie.ReadyState -ne 4 -or $ie.Busy ){Start-Sleep -m 100}

        if ( $ie.ReadyState -eq 4 ) {

            $elementText = $ie.document.getElementsByTagName('a')  | ? { $_.href -match $elementMatchText}  | Select  
            $elementMatch = $elementText.innerText -match $elementMatchText

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

        }

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

    } until ( $exitFlag )
}

# Main function
function doCrawl() {

    Param( [ipAddress]$url )
    

    write-host "Working IP" $url.ToString()
    # Go to the IP
    $ie.Navigate( "$url" )
    # Wait for it to load
    while( $ie.ReadyState -ne 4 -or $ie.Busy ){Start-Sleep -m 1} 
    # Skip cert errors (thank you, Vidyo, for those)
    if ($ie.document.url -Match "SSLerror")
            {
            #"Bypassing SSL Certificate Error Page"; # Shhhh... so noisy
            $sslbypass=$ie.Document.getElementsByTagName("a") | where-object {$_.name -eq "overridelink"};
            $sslbypass.click();
            #"Sleep  while final page loads"; # Yeah, more noise
            Start-Sleep -s 1;
            while( $ie.ReadyState -ne 4){Start-Sleep -m 100};
                        } 

    # Ensure the login page loads
    domWaitID "username" ""

    # Populate user/password fields. Defaults are plaintext in this file, sorry. Defined in variable definitions, above.
    $ie.document.getElementByID("username").value = $username
    $ie.document.getElementByID("password").value = $password

    # Click the login button (Ermergerd; this took way longer than it should have to figure out.
    # Essentially had everything right yesterday, but hafta add the Select statement to allow
    # the Click() method to proc without throwing errors)
    $clicky = $ie.document.getelementsbytagname('button') | Select
    $clicky.click()

    # Wait for post-login page to load
    domWaitHREF "shutdown"

    # Find and click the Shutdown page link
    #Start-sleep -s 1
    $shutdownLink = $ie.document.getElementsByTagName('a')  | ? { $_.href -match "shutdown"} | Select
    $shutdownLink.Click()

    # Ensure the Shutdown page loads
    domWaitHREF "shutdown"
     
    # Populate user/password fields in shutdown page. They're plaintext in this file, sorry. Defined in variable definitions, above.
    write-host $ie.document.outerHTML
    $ie.document.getElementByID("shutdownusername").value = "$username"
    $ie.document.getElementByID("shutdownpassword").value = "$password"

    # Click the Restart button 
    $clickyReboot = $ie.document.getElementsByTagName('button')  | ? { $_.innerText -match "Restart"} | Select
    $clickyReboot.click()
    write-host $url "is rebooting."    

    loadWait

} # End of main method doCrawl()


# Core code *****************************************************************************

# Irrelevant; we're not catching errors.
$ErrorActionPreference = "continue"
# Clear (lol)
clear

# Launch a new IE object; we only want to do this once per script run and iterate through all IP
# addresses before closing it.
$ie = New-Object -comobject InternetExplorer.Application 
# Change next line to $true if you want to see the magic happen onscreen. Might be useful to troubleshoot, as
# the non-existant error-trap tends to quash any useful text tossed onscreen
$ie.visible = $true 
$ie.silent = $false

# Call main method
Get-Content $inputFile | ForEach-Object {doCrawl -url $_ }

# Close the browser instance
$ie.Quit()

 

Share this post


Link to post
Share on other sites
Danp2
1 hour ago, wisem2540 said:

if ($ie.document.url -Match "SSLerror")

You could perform a similar check after using _IEPropertyGet to retrieve the current URL. If found, then retrieve / click the link

Share this post


Link to post
Share on other sites
Danp2

For the other stuff, there are lots of examples on the forum of using _IETagNameGetCollection and then looping through the matching elements. Here are a couple of examples --

 

Share this post


Link to post
Share on other sites
wisem2540
1 hour ago, Danp2 said:

You could perform a similar check after using _IEPropertyGet to retrieve the current URL. If found, then retrieve / click the link

I will check this out for sure.  Thanks.

 

As for the looping through to get the matching elements...  Isn't that pretty much what I am already doing?  I was hoping, since I already know the strings I am looking for, that I could target them directly.

 

Share this post


Link to post
Share on other sites
Danp2

Yes, except that you are looping through all elements. If you switch to _IETagNameGetCollection, then you can reduce the elements search to a specific type (button, link, input, etc).

As far as directly targeting an element, you could look into querySelector (search the forum for examples) or jQuerify.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×