Jump to content

Make _IECreate() return if IE is closed


Recommended Posts

I use the _IECreate function to start a new instance of IE. If I close the new IE window before the page I have specified can load, the script hangs. How can I have the script immediately return only if IE is closed before the page has fully loaded?

I know about the $f_wait parameter but, do not believe that is what I need here and if so, do not understand how it can help me to accomplish my goal.

If I add in the _IELoadWaitTimeout function, the script will return after the timeout occurs (as expected) but, I get this in the console:

C:\Program Files\AutoIt3\Include\IE.au3 (1111) : ==> The requested action with this object has failed.:

Local $o_col = $o_object.document.forms.item($s_Name)

Local $o_col = $o_object.document^ ERROR

As my script has a GUI, I am not satisfied with using a timeout anyway or this would work. I need for the script to return immediately for if the user wishes to exit out of both IE and my GUI before the page load event occurs.

Link to comment
Share on other sites

You can make the error non-fatal by adding _IEErrorHandlerRegister()

Suggest you set creation not to wait and then look at using ObjEvent with the $oIE object to register for notification of OnQuit

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

Okay. I now have my script to where I can write to the console when IE is quit and optionally exit my script but, that is the only thing I seem to be able to do. How can I have the function that is called by ObjEvent return to my GUI's while loop instead of having to exit the script? Is it possible to return to a while loop when you are inside of a function? "Return" does not seem to work and I believe this is because I am having one function call another so it is simply returning to the previous function instead of my loop. How can I fix this?

My error may very well be in the code so here is the relevant pieces:

This function is what I use to create the IE instance when a button is clicked in my GUI.

Func createIE($url, $form, $login)
    $oIE = _IECreate($url, -1, -1, 0)
    ObjEvent($oIE, "IEEvent_")
    _IELoadWait($oIE)
    $o_form = _IEFormGetObjByName($oIE, $form)
    $o_login = _IEFormElementGetObjByName($o_form, $login)
    _IEFormElementSetValue($o_login, $card_num)
    _IEFormSubmit($o_form, 0)
EndFunc

This is the IEEvent function that gets called:

Func IEEvent_Quit()
    ConsoleWrite("IE was closed!" & @CRLF)
    Exit ;for now, just exit since I do not know how to return to my while loop from here
EndFunc

By the way, thank you for pointing me in the right direction. I feel closer now as I can always just exit and have the user restart the program but, I'd prefer that not happen. :huh2:

Link to comment
Share on other sites

Maybe put a Return statement in your createIE() function?

Edit/add: In your createIE() function before _IELoadWait($oIE) make it check to see if $oIE is an object and if not, Return.

Edited by MrMitchell
Link to comment
Share on other sites

Set a global variable in your event routine and act upon it in your main program by either placing your entire main code inside a While loop or by checking the value of the global prior to particular actions.

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

First off, thank you to you both for replying.

Now, I believe I have finally tracked down the cause of my problems and (hopefully) correctly fixed the issue.

The problem I had was with the _IELoadWait function itself. Through trial and error, I found that the _IELoadWait was hanging no matter what I tried if the browser did not exist. Again, through trial and error, I narrowed the problem to this piece of code within the IE.au3 UDF:

While Not (String($o_object.readyState) = "complete" Or $o_object.readyState = 4 Or $f_Abort)
                ; Trap unrecoverable COM errors
                If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
                    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
                    $f_Abort = True
                EndIf
                If @error = $_IEStatus_ComError And __IEComErrorUnrecoverable() Then
                    $i_ErrorStatusCode = __IEComErrorUnrecoverable()
                    $f_Abort = True
                EndIf
                Sleep(100)
            WEnd

I have added in:

If Not ObjName($o_object) Then
                    $i_ErrorStatusCode = __IEComErrorUnrecoverable()
                    $f_Abort = True
                EndIf

So that the piece of code now looks like:

While Not (String($o_object.readyState) = "complete" Or $o_object.readyState = 4 Or $f_Abort)
                ; Trap unrecoverable COM errors
                If (TimerDiff($IELoadWaitTimer) > $i_timeout) Then
                    $i_ErrorStatusCode = $_IEStatus_LoadWaitTimeout
                    $f_Abort = True
                EndIf
                If @error = $_IEStatus_ComError And __IEComErrorUnrecoverable() Then
                    $i_ErrorStatusCode = __IEComErrorUnrecoverable()
                    $f_Abort = True
                EndIf
                If Not ObjName($o_object) Then
                    $i_ErrorStatusCode = __IEComErrorUnrecoverable()
                    $f_Abort = True
                EndIf
                Sleep(100)
            WEnd

Now my question is: Have I correctly resolved my issue? Or do I need to go about it another way? If I have done so correctly, will this be added to the UDF and should I replicate the code on the other While statements in the same place I have on this one?

At least it is working for me now. :huh2: Thank you again for all the help!

Link to comment
Share on other sites

Actually, if you have discovered a new unrecoverable error, it needs to be added to this routine:

; #INTERNAL_USE_ONLY# ===========================================================================================================
; Name...........: __IEComErrorUnrecoverable
; Description ...: Internal function to test a COM error condition and determine if it is considered unrecoverable
; Parameters ....: None, relies on Global variables
; Return values .: Unrecoverable: True, Else: False
; Author ........: Dale Hohm
; ===============================================================================================================================
Func __IEComErrorUnrecoverable()
    Select
        ;
        ; Cross-site scripting security error
        Case ($IEComErrorNumber = -2147352567) Or (String($IEComErrorDescription) = "Access is denied.")
            Return $_IEStatus_AccessIsDenied
            ;
            ; Browser object is destroyed before we try to operate upon it
        Case ($IEComErrorNumber = -2147417848) Or (String($IEComErrorWinDescription) = "The object invoked has disconnected from its clients.")
            Return $_IEStatus_ClientDisconnected
            ;
        Case Else
            Return $_IEStatus_Success
    EndSelect
EndFunc   ;==>__IEComErrorUnrecoverable

So, what is the COM error code and description you have returned? Your scenario is what this line is supposed to catch:

Case ($IEComErrorNumber = -2147417848) Or (String($IEComErrorWinDescription) = "The object invoked has disconnected from its clients.")

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

Is this what you are needing to know?

--> COM Error Encountered in test.au3
----> $IEComErrorScriptline = 1143
----> $IEComErrorNumberHex = 800706BA
----> $IEComErrorNumber = -2147023174
----> $IEComErrorWinDescription = The RPC server is unavailable.
----> $IEComErrorDescription = 
----> $IEComErrorSource = 
----> $IEComErrorHelpFile = 
----> $IEComErrorHelpContext = 
----> $IEComErrorLastDllError = 0

--> COM Error Encountered in test.au3
----> $IEComErrorScriptline = 1156
----> $IEComErrorNumberHex = 800706BA
----> $IEComErrorNumber = -2147023174
----> $IEComErrorWinDescription = The RPC server is unavailable.
----> $IEComErrorDescription = 
----> $IEComErrorSource = 
----> $IEComErrorHelpFile = 
----> $IEComErrorHelpContext = 
----> $IEComErrorLastDllError = 0

I get that when I use the code I have added in to my script from the help file on the _IEErrorHandlerRegister function.

Link to comment
Share on other sites

I cannot produce the error you show.

Can you provide a small reproducer?

Dale

Free Internet Tools: DebugBar, AutoIt IE Builder, HTTP UDF, MODIV2, IE Developer Toolbar, IEDocMon, Fiddler, HTML Validator, WGet, curl

MSDN docs: InternetExplorer Object, Document Object, Overviews and Tutorials, DHTML Objects, DHTML Events, WinHttpRequest, XmlHttpRequest, Cross-Frame Scripting, Office object model

Automate input type=file (Related)

Alternative to _IECreateEmbedded? better: _IECreatePseudoEmbedded  Better Better?

IE.au3 issues with Vista - Workarounds

SciTe Debug mode - it's magic: #AutoIt3Wrapper_run_debug_mode=Y

Doesn't work needs to be ripped out of the troubleshooting lexicon. It means that what you tried did not produce the results you expected. It begs the questions 1) what did you try?, 2) what did you expect? and 3) what happened instead?

Reproducer: a small (the smallest?) piece of stand-alone code that demonstrates your trouble

Link to comment
Share on other sites

Here you go:

#include<IE.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>
GUICreate("Test", 100, 100)
$button = GUICtrlCreateButton("Be fast!", 25, 35)
GUISetState(@SW_SHOW)
While 1
       $msg = GUIGetMsg()
    Select
    Case $msg = $GUI_EVENT_CLOSE
        ExitLoop
    Case $msg = $button
        yahoo()
    EndSelect
WEnd

Func createIE($url, $form, $login)
    ; Register a customer error handler
    _IEErrorHandlerRegister ("MyErrFunc")
    $oIE = _IECreate($url, -1, -1, 0)
    _IELoadWait($oIE, -1, 10000)
    ; Deregister the customer error handler
    _IEErrorHandlerDeregister ()
    ; Register the default IE.au3 COM Error Handler
    _IEErrorHandlerRegister ()
    $o_form = _IEFormGetObjByName($oIE, $form)
    $o_login = _IEFormElementGetObjByName($o_form, $login)
    _IEFormElementSetValue($o_login, "test")
    _IEFormSubmit($o_form, 0)
EndFunc

Func yahoo()
    createIE("http://yahoo.com", "sf1", "p")
EndFunc

Func MyErrFunc()
    ; Important: the error object variable MUST be named $oIEErrorHandler
    $ErrorScriptline = $oIEErrorHandler.scriptline
    $ErrorNumber = $oIEErrorHandler.number
    $ErrorNumberHex = Hex($oIEErrorHandler.number, 8)
    $ErrorDescription = StringStripWS($oIEErrorHandler.description, 2)
    $ErrorWinDescription = StringStripWS($oIEErrorHandler.WinDescription, 2)
    $ErrorSource = $oIEErrorHandler.Source
    $ErrorHelpFile = $oIEErrorHandler.HelpFile
    $ErrorHelpContext = $oIEErrorHandler.HelpContext
    $ErrorLastDllError = $oIEErrorHandler.LastDllError
    $ErrorOutput = ""
    $ErrorOutput &= "--> COM Error Encountered in " & @ScriptName & @CR
    $ErrorOutput &= "----> $ErrorScriptline = " & $ErrorScriptline & @CR
    $ErrorOutput &= "----> $ErrorNumberHex = " & $ErrorNumberHex & @CR
    $ErrorOutput &= "----> $ErrorNumber = " & $ErrorNumber & @CR
    $ErrorOutput &= "----> $ErrorWinDescription = " & $ErrorWinDescription & @CR
    $ErrorOutput &= "----> $ErrorDescription = " & $ErrorDescription & @CR
    $ErrorOutput &= "----> $ErrorSource = " & $ErrorSource & @CR
    $ErrorOutput &= "----> $ErrorHelpFile = " & $ErrorHelpFile & @CR
    $ErrorOutput &= "----> $ErrorHelpContext = " & $ErrorHelpContext & @CR
    $ErrorOutput &= "----> $ErrorLastDllError = " & $ErrorLastDllError
    MsgBox(0,"COM Error", $ErrorOutput)
    SetError(1)
    Return
EndFunc  ;==>MyErrFunc

This just simply goes to Yahoo and submits a search for "test" if left to run as intended. However, if you are quick enough to close the IE window before/while the _IELoadWait function takes place, then the script will become unresponsive until the timeout has expired when using an unmodified IE.au3. If you do not specify a timeout, then the script will be unresponsive for 5 minutes as that is the default timeout. I get the same results on both a Win7 machine with IE9 and a WinXP machine wiht IE 8.

I only stumbled upon this because I accidentally clicked one of my buttons in my original script and immediately exited IE before the script could finish, leaving my GUI unresponsive.

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...