Jump to content

Cannot reach "body" property in COM Object "Shell.Explorer" with Autoit 3.3.16.1


Go to solution Solved by Gianni,

Recommended Posts

Posted

Good day everybody, I just upgraded Autoit from version 3.3.14.5 to 3.3.16.1 and programs that use Shell.Explorer.2 COM Object are not working anymore.

Nothing else has changed in the system, the program failed just after updating AutoIt.

The original program is bigger but I can show the issue for instance in this small program to write in the body of the html document:

#include <GuiConstants.au3>

Global $GUI_IE, $btnCerrar, $oIE, $ancho = 200, $alto = 150

Global $oErrorHandler = ObjEvent("AutoIt.Error", "_ErrFunc")
#forceref $oErrorHandler

$GUI_IE = GUICreate("Shell Explorer", $ancho,$alto, -1,-1, BitOr($WS_CAPTION, $WS_POPUP, $WS_CLIPCHILDREN))
$btnCerrar = GUICtrlCreateButton("Close", ($ancho-60)/2,$alto-30, 60,24)

$oIE = ObjCreate("Shell.Explorer.2")
GUICtrlCreateObj($oIE, 10,10, $ancho-20,$alto-46)
$oIE.navigate("about:blank")
;$oIE.navigate("https://www.example.com")

$oIE.document.body.innerHTML = "<p>HELLO</p>"
While $oIE.busy
    Sleep(50)
WEnd
GUISetState(@SW_SHOW, $GUI_IE)

While 1
    Switch GUIGetMsg()
        Case $btnCerrar, $GUI_EVENT_CLOSE
            ExitLoop
    EndSwitch
WEnd
GUIDelete($GUI_IE)
$oIE=0

Func _ErrFunc($oError)
    ConsoleWrite(@ScriptName & " (" & $oError.scriptline & ") : ==> COM Error intercepted !" & @CRLF & _
       @TAB & "err.number is: " & @TAB & @TAB & "0x" & Hex($oError.number) & @CRLF & _
       @TAB & "err.windescription:" & @TAB & $oError.windescription & @CRLF & _
       @TAB & "err.lastdllerror is: " & @TAB & $oError.lastdllerror & @CRLF & _
       @TAB & "err.scriptline is: " & @TAB & $oError.scriptline & @CRLF & _
       @TAB & "err.retcode is: " & @TAB & "0x" & Hex($oError.retcode) & @CRLF & @CRLF)
EndFunc   ;==>_ErrFunc

 

_ErrFunc() is showing error 0x00000003: "Object Invoke failed" in the line with [$oIE.document.body.innerHTML = "<p>HELLO</p>"]

To narrow the problem source I have split the access to the property with:

Global $doc = $oIE.Document
ConsoleWrite("Document is Object: " & IsObj($doc) & @CRLF) ;Returns 1 (object ok)
Global $body = $doc.body
ConsoleWrite("body is Object: " & IsObj($body) & @CRLF) ;Returns 0 (not object!)
$body.innerHTML = "<p>HELLO</p>" ;Obviously fails since $body is not an object

$oiE.Document works and I can invoke other methods on $doc.

But $doc.body doesn´t return an object (Error: Object Invoke failed).

Please notice: the problem is not starting with "about:blank", you can navigate to a full page (like "http://www.example.com" or "https://www.autoitscript.com") and body property is not accessible either.

The problem isn't that I try to modify it with innerHTML, just trying to read the body already fails.

All this worked without changes in v3.3.14.5. I know in the last version there have been some changes in COM error handling but I don't think I have to do something different to avoid the error in this version.

Am I doing anything wrong?

Thank you.

 

 

  • Solution
Posted

Hi @Ximorro, shouldn't you place the innerHTML setting after the $oIE "busy" status check?
however I think checking the "busy" status is not enough.
try with this 2 lines:

Do
    Sleep(50)
Until ($oIE.readyState = 'complete' Or $oIE.readyState = 4)

$oIE.document.body.innerHTML = "<p>HELLO</p>"

instead of

$oIE.document.body.innerHTML = "<p>HELLO</p>"
While $oIE.busy
    Sleep(50)
WEnd

 

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Posted

Hi Gianni!

Well, when creating a blank page using about:blank that's not necessary, at least in my tests the body is always ready immediately. That's how I use it so I left the code like that. (I use this to show small formatted help windows in my programs)

You are right that when loading a web page, like with $oIE.navigate("https://www.example.com"), it's advisable to wait for it to be ready before modifying it.

I already tried putting the waiting loop before accessing the body and it didn´t work but I didn't think about "readyState", let me test...

IT WORKS!

So the trick here is to use "$oIE.readyState" instead of "$oIE.busy". I misunderstood then this method because the documentatio says:

Busy property: Gets a value that indicates whether the object is engaged in a navigation or downloading operation.

So I thought that when not busy all was clear.

So the explanation must be Autoit v3.3.16.1 needs more time to get the page ready and checking for busy (before accessing, not like in my example) is not enough because it can be "not busy" but still not completely ready.

One question, where can I read info about those string status for readyState like 'complete' you use? In MSN documentation I only see reference to READYSTATE enumeration so only info about integer values (and the constants for C that we cannot use in AutoIt directly)

Thanks Gianni! I'll check in my more convoluted programs but clearly checking for readyState instead of busy fixes these examples so I'm giving you the solution mark.

Very appreciated, I was getting nuts, checking in different OS, x64 or x32, reinstalling v.3.3.14.5 (where it worked again)...

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
  • Recently Browsing   0 members

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