Jump to content
Tippex

How can I check if an object's property exists?

Recommended Posts

Tippex

I'm having a problem with _IEBodyReadText() which is a function from the IE.au3 UDF include.

Quote

    Version:  T3.0-1
    Last Update: 13/06/02
    Requirements: AutoIt3 3.3.9 or higher

    Update History:
    ===================================================
    T3.0-2 14/8/19

My problem is that randomly it will crash my script with:

Return SetError($_IESTATUS_Success, 0, $oObject.document.body.innerText)
Return SetError($_IESTATUS_Success, 0, $oObject.document.body^ ERROR

I don't know why the error isn't caught by __IEErrorHandlerRegister but looking at this function, I can see that there is a check done by IsObj($oObject) to ensure that the object "$oObject" exists but no check that it contains the property "innerText"

; #FUNCTION# ====================================================================================================================
; Author ........: Dale Hohm
; ===============================================================================================================================
Func _IEBodyReadText(ByRef $oObject)
    If Not IsObj($oObject) Then
        __IEConsoleWriteError("Error", "_IEBodyReadText", "$_IESTATUS_InvalidDataType")
        Return SetError($_IESTATUS_InvalidDataType, 1, 0)
    EndIf
    If Not __IEIsObjType($oObject, "browserdom") Then
        __IEConsoleWriteError("Error", "_IEBodyReadText", "$_IESTATUS_InvalidObjectType", "Expected document element")
        Return SetError($_IESTATUS_InvalidObjectType, 1, 0)
    EndIf
    ;
    Return SetError($_IESTATUS_Success, 0, $oObject.document.body.innerText)
EndFunc   ;==>_IEBodyReadText

I'm struggling to find out how to test if "$oObject.document.body.innerText" exists before allowing the following Return statement to reference it with the assumption that it does exist (crashing my script when it doesn't).

Any ideas please?

Share this post


Link to post
Share on other sites
Tippex

Thank you.

I'll try that now.

Share this post


Link to post
Share on other sites
water
1 hour ago, Tippex said:

I don't know why the error isn't caught by __IEErrorHandlerRegister

Couldn't find a place where this function gets called in the UDF.


My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2018-10-19 - Version 1.4.10.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (2018-10-31 - Version 1.3.4.1) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2017-07-21 - Version 0.4.0.1) - Download - General Help & Support - Example Scripts
PowerPoint (2017-06-06 - Version 0.0.5.0) - Download - General Help & Support
Excel - Example Scripts - Wiki
Word - Wiki
 
Tutorials:

ADO - Wiki

 

Share this post


Link to post
Share on other sites
Tippex

Thank you.

Error handling appears to be switched on and off as needed in some IE.au3 functions but missing for this particular function.

I think the necessary fix to stabilise this function may be something like:

Func _IEBodyReadText(ByRef $oObject)
    If Not IsObj($oObject) Then
        __IEConsoleWriteError("Error", "_IEBodyReadText", "$_IESTATUS_InvalidDataType")
        Return SetError($_IESTATUS_InvalidDataType, 1, 0)
    EndIf
    If Not __IEIsObjType($oObject, "browserdom") Then
        __IEConsoleWriteError("Error", "_IEBodyReadText", "$_IESTATUS_InvalidObjectType", "Expected document element")
        Return SetError($_IESTATUS_InvalidObjectType, 1, 0)
    EndIf

    ;------------------------------------------------------------------------------------------
    ; Check to verify that the document body object has an innerText property, if not, skip trying to return its contents
    ;
    ; Setup internal error handler to Trap COM errors, turn off error notification,
    ;     check object property validity, set a flag and reset error handler and notification
    ;
    Local $bIsInnerText = True
    ; Trap COM errors and turn off error notification
    $bStatus = __IEInternalErrorHandlerRegister()
    If Not $bStatus Then __IEConsoleWriteError("Warning", "_IEBodyReadText", _
            "Cannot register internal error handler, cannot trap COM errors", _
            "Use _IEErrorHandlerRegister() to register a user error handler")
    ; Turn off error notification for internal processing
    $iNotifyStatus = _IEErrorNotify() ; save current error notify status
    _IEErrorNotify(False)

    ; Check conditions to verify that the object is a browser
    If $bIsInnerText Then
        $sTmp = $oObject.document.body.innerText ; Is .innerText a valid property?
        If @error Then $bIsInnerText = False
    EndIf

    ; restore error notify
    _IEErrorNotify($iNotifyStatus) ; restore notification status
    __IEInternalErrorHandlerDeRegister()
    ;------------------------------------------------------------------------------------------

    If $bIsInnerText Then   
        Return SetError($_IESTATUS_Success, 0, $oObject.document.body.innerText)
    Else
        __IEConsoleWriteError("Error", "_IEBodyReadText", "$_IESTATUS_InvalidObjectType", "Expected innerText element")
        Return SetError($_IESTATUS_InvalidObjectType, 1, 0)     
    EndIf
        
EndFunc   ;==>_IEBodyReadText

 

May I ask why calling it with an execute catches errors better please?

Thanks

 

 

 

 

 

 

Edited by Tippex

Share this post


Link to post
Share on other sites
genius257
3 minutes ago, junkew said:

Out of interest but under which circumstance there would not be a document.body.innertext property available? 
As far as I know IE has this property allways.

when loading for example. But i am sure there exists rare circumstances where this problem would occur.

  • Like 1

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

  • Similar Content

    • careca
      By careca
      Hi, i feel im close to getting it to work, but there must be something im missing that's probably easy for you experts.
      #include <IE.au3> #include <File.au3> #include <MsgBoxConstants.au3> $Visible = 1 Local $oIE $oIE = _IECreate("https://beemp3s.net/mp3-download.html", 0, $Visible, 1, 1) _IELoadWait($oIE) If $oIE <> @error Then ;_ArrayText() _QuerySite('Finding Hope - Without You') ;_IEQuit($oIE) ;Exit Else MsgBox(64 + 262144, 'Fail', 'Could not create a new window') EndIf ;============================================================================= Func _QuerySite($Name) Local $oIE_ObjectToSearch = _IEGetObjById($oIE, 'query') _IEDocInsertText($oIE_ObjectToSearch, $Name) Local $oIE_ObjectToClick = _IEGetObjById($oIE, "search-action") _IEAction($oIE_ObjectToClick, 'click') _IELoadWait($oIE, 2000) ;============================================================================= Local $oSubmitClick = _IEGetObjById($oIE, "col-md-12") _IEAction($oSubmitClick, "click") _IELoadWait($oIE, 2000) ;============================================================================= Local $oBtns = _IETagNameGetCollection($oIE, "div") For $oBtn In $oBtns If String($oBtn.classname) = "col-md-12" Then If String($oBtn.innertext) = "Download / Play" Then ConsoleWrite($oBtn.innertext & @CRLF) _IEAction($oBtn, 'click') EndIf EndIf Next ;============================================================================= ;Local $oElements = _IETagNameAllGetCollection($oIE) ;For $oElement In $oElements ; If $oElement.id Then MsgBox($MB_SYSTEMMODAL, "Element Info", "Tagname: " & $oElement.tagname & @CRLF & "id: " & $oElement.id & @CRLF & "innerText: " & $oElement.innerText) ;Next ;============================================================================= ;_IEQuit($oIE) ;Exit ;============================================================================= EndFunc ;==>_QuerySite ;============================================================================= Func _ArrayText() If FileExists('Titles.txt') Then Local $FO = FileOpen('Titles.txt') Local $R2A = FileReadToArray($FO) Local $iLineCount = @extended FileClose($FO) For $f = 0 To $iLineCount - 1 ConsoleWrite($f & ' - ' & $R2A[$f] & @CRLF) _QuerySite($R2A[$f]) Next Else MsgBox(64 + 262144, 'Fail', 'Could not find the file Titles.txt') EndIf EndFunc ;==>_ArrayText ;============================================================================= The idea is to get into this site, write into the search and click, which i did, but now the problem is clicking in any of the buttons in the results page, im looking for a way to click the first one, it always matches to what i want, so no need to fiddle around.
      Site
      Thanks for help in advance.

    • yoschga
      By yoschga
      is there a possibility to let ie.au3 click into a form? i use on a project where i need to click into a form where items are loaded just writing it in or fill the form is no option
       

    • RamaKrishna9
      By RamaKrishna9
      What are the minimum system requirements(like Windows OS version, IE browser version, etc,.) for IE.au3(3.3.14.2) to work properly?
    • MakzNovice
      By MakzNovice
      Hello Experts,
      I am working on modifying table data of a browser currently in IE (soon in FF)
      My sequence of operations:
      1. Activate Browser
      2. Get Browser table
      3. Modify data  in table
      4. Suppress any warning/error message from webpage
      5. Activate the Webpage again 
      6. Send {F11} key sequence twice to achieve some update without Updating form ( {F5})
       
      My problem is at Step 5, as it activates the wrong window ( last used application rather than my browser window)
      My code snippet for it as follows
      $bFoundWindow = False Local $aList = WinList("[REGEXPTITLE:(?i)(.*Internet Explorer.*)]") Local $hWND = 0 For $i = 1 To $aList[0][0] If False = $bFoundWindow And $aList[$i][0] <> "" And BitAND(WinGetState($aList[$i][1]), 1) Then WinActivate($aList[$i][1]) ; 1. Activate Browser window WinSetState ( $aList[$i][1], "", @SW_MAXIMIZE) $hWND = $aList[$i][1] $objEditIE = _IEAttach ($aList[$i][1], "hwnd") $oTitles = _IETagNameGetCollection($objEditIE, "TITLE") For $oTitle In $oTitles $sTitle = $oTitle.innerText If $sTitle = $searchString Then MsgBox(0,"APPLICATION Found", "Got Edit List Window", 1) $bFoundWindow = True ExitLoop EndIf Next EndIf Next If False = $bFoundWindow Then MsgBox(0,"Error","Please launch Edit window for updating values in Browser prior to script execution",10) Exit EndIf ; MY CODE HERE TO MODIFY TABLE ; 2. Get Browser table ; 3. Modify data  in table ; Check if message from webpage pop-up window exists if so click ok on it Local $nCounter = 0 Local $nMaxCounter = 5 while 1 If WinExists("Message from webpage","") Then ControlClick("Message from webpage","","Button1","primary",1) ;4. Suppress any warning/error message from webpage Else $nCounter = $nCounter + 1 Sleep(100) ;MsgBox(0,"Counter", $nCounter, 1) If $nCounter = $nMaxCounter Then ExitLoop EndIf WEnd ;5. Activate the Webpage again  WinActivate($hWND) ; have already tried WinActivate($aList[$i][1]) but no success ;6. Send {F11} key sequence twice to achieve some update without Updating form ( {F5}) Send("{F11}") WinActivate($hWND) ;WinActivate($aList[$i][1]) Sleep(100) Send("{F11}") Any support will be highly appreciated
    • MakzNovice
      By MakzNovice
      Hello Experts,
      I am working on custom application details of which I am unable to share.
      But here is statement of my problem, I have two IE windows one window with Title "Parent " and other with "TableEdit", but for some reason when I get WinList they are shown as 2 processes each. ( see attached image)
      Since my most important motive is to modify table data in 'TableEdit' I try to access the table in it
      My code snippet is 
      ***********************************************************************************************
      $searchString = "TableEdit"
      Local $aList = WinList("[REGEXPTITLE:(?i)(.*Internet Explorer.*)]")
      _ArrayDisplay($aList)
      For $i = 1 To $aList[0][0]
          If $aList[$i][0] <> "" And BitAND(WinGetState($aList[$i][1]), 2) Then
              ;MsgBox($MB_SYSTEMMODAL, "", "Title: " & $aList[$i][0] & @CRLF & "Handle: " & $aList[$i][1])
              If 0 <> StringInStr($aList[$i][0],"TableEdit") Then
                  $objEditIE = _IEAttach ($aList[$i][1])
                  ExitLoop
              EndIf
          EndIf
      Next
      WinActivate($objEditIE)
      $oPageContentListFrame = _IEFrameGetObjByName($objEditIE, "iframe_1")
      $iNumFrames = @extended
      MsgBox(0,"Got pagecontent",@error) ; returns 3, indicating invalid data type
      MsgBox(0,"Number of Frame",$iNumFrames) ; returns 1, expected value is 1 
      ***********************************************************************************************
      and If I do code as below the return value is different
      $searchString = "TableEdit"
       $objEditIE = _IEAttach ($searchString, "title")
      WinActivate($objEditIE)
      $oPageContentListFrame = _IEFrameGetObjByName($objEditIE, "iframe_1")
      $iNumFrames = @extended
      MsgBox(0,"Got pagecontent",@error) ; returns 0
      MsgBox(0,"Number of Frame",$iNumFrames) ; returns 0. expected value is 1
      ***********************************************************************************************
      What is wrong with my code? 
      Why do I see two process each for IE for each window?
       
      WinListImage.bmp
×