Jump to content

Help Improving my IE automation script


Recommended Posts

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

 

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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>

 

Link to comment
Share on other sites

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()

 

Link to comment
Share on other sites

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.

 

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...