Jump to content

OnEventMode - button stops working if _IECreate() is interrupted


wuruoyu
 Share

Recommended Posts

Press button to go to the website with _IECreate(), if IE window is closed before website is loaded, the button is no longer working.

In another script, I am able to use OBJEvent to monitor if IE window is abruptly closed, then restart the whole script, but in ideal scenario:lol: I don't want to restart the whole script. Thank you in advance for any help or suggestion :)

To reproduce:

1. Click on "Open Website" button, wait for IE window to open and quickly click the red "X" button to close the IE window before the website finishes loading. 

2. "Open Website" button is no longer working.

#NoTrayIcon
#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiButton.au3>
#include <EditConstants.au3>
#include <IE.au3>

Opt("GUIOnEventMode", 1)

;_IEErrorHandlerRegister(_IEErrorFunc)

Global $OpenWebsiteButton, $openWebsiteButtonFlg, $IEHWND

_main()

Func _IEErrorFunc($oError)
    ConsoleWrite(@ScriptFullPath & " (" & $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.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @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   ;==>_IEErrorFunc

Func _main()
    $main = GUICreate("main", 143, 63, -1, -1, -1, -1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_exit")

    $OpenWebsiteButton = GUICtrlCreateButton("Open Website", 20, 20, 100, 20, -1, -1)
    GUICtrlSetOnEvent(-1, "_openWebsiteButton")

    GUISetState(@SW_SHOW, $main)

    While 1
        Select
        Case $openWebsiteButtonFlg = True
                _openWebsiteButtonAction()
                $openWebsiteButtonFlg = False
        EndSelect
        Sleep(100)
    WEnd
EndFunc   ;==>_main

Func _exit()
    Exit
EndFunc   ;==>_exit

Func _openWebsiteButton()
    Switch @GUI_CtrlId
        Case $OpenWebsiteButton
            $openWebsiteButtonFlg = True
    EndSwitch
EndFunc

Func _openWebsiteButtonAction()
    If ObjName($IEHWND) = "IWebBrowser2" Then
        _IEQuit($IEHWND)
        ;If @error Then Return SetError(@error, @extended, -1)
    EndIf
    Local $url = "https://www.autoitscript.com/site/"
    _IECreate($url, 0, 1, 0)
    ;If @error Then Return SetError(@error, @extended, -1)

    Local $websiteTimer = TimerInit()
    Do
        While 1
            $aWinList = WinList("[CLASS:IEFrame]")
            For $i = 1 To $aWinList[0][0]
                If BitAND(WinGetState($aWinList[$i][1]), 2) And StringInStr(WinGetText($aWinList[$i][1]), $url) Then
                    $IEHWND = _IEAttach($aWinList[$i][1], "hwnd")
                    ;If @error Then Return SetError(@error, @extended, -1)
                    ExitLoop 3
                EndIf
            Next
        WEnd
    Until TimerDiff($websiteTimer) > 6000
EndFunc

 

Edited by wuruoyu
Link to comment
Share on other sites

This seems to work, but you will have to test it.

Func _openWebsiteButtonAction()
    If ObjName($IEHWND) = "IWebBrowser2" Then
        _IEQuit($IEHWND)
        ;If @error Then Return SetError(@error, @extended, -1)
    EndIf
    Local $url = "https://www.autoitscript.com/site/"
    _IECreate($url, 0, 1, 0)
    ;If @error Then Return SetError(@error, @extended, -1)

    Local $websiteTimer = TimerInit()
    Do
        While 1
            $aWinList = WinList("[CLASS:IEFrame]")
            For $i = 1 To $aWinList[0][0]
                If BitAND(WinGetState($aWinList[$i][1]), 2) And StringInStr(WinGetText($aWinList[$i][1]), $url) Then
                    $IEHWND = _IEAttach($aWinList[$i][1], "hwnd")
                    ;If @error Then Return SetError(@error, @extended, -1)
                    ExitLoop 3
                EndIf
            Next
        WEnd
    Until TimerDiff($websiteTimer) > 6000
    $openWebsiteButtonFlg = False ; <<<<<<<<<<< ADDED THIS LINE <<<<<<<<<<<<
EndFunc

Edit
I'm not sure why you need the function _openWebsiteButton().

Oops, sorry. Now I understand the problem. I was too slow in clicking the red x.

Edited by czardas
Link to comment
Share on other sites

Thank you czardas for the quick reply. I did try the same thing earlier and just now, it's still not working. P.S to successfully reproduce the problem, I have to close the IE window really really fast (right when it's launched).

Link to comment
Share on other sites

I must admit that I find this a bit hard to understand. I tend to use message loop mode and not so much GUICtrlSetOnEvent(). Anyway I have tried a few things, but I'm not entirely satisfied with what I tried. This seems to be my best attempt, without completely rewriting your code. I don't yet know why it behaves the way it does. If it works, this not a fix: it's a patch.

#NoTrayIcon
#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiButton.au3>
#include <EditConstants.au3>
#include <IE.au3>

Opt("GUIOnEventMode", 1)

;_IEErrorHandlerRegister(_IEErrorFunc)

Global $OpenWebsiteButton, $openWebsiteButtonFlg = False, $IEHWND, $IE_TITLE = False

_main()

Func _IEErrorFunc($oError)
    ConsoleWrite(@ScriptFullPath & " (" & $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.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @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   ;==>_IEErrorFunc

Func _main()
    $main = GUICreate("main", 143, 63, -1, -1, -1, -1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_exit")

    $OpenWebsiteButton = GUICtrlCreateButton("Open Website", 20, 20, 100, 20, -1, -1)
    GUICtrlSetOnEvent(-1, "_openWebsiteButton")

    GUISetState(@SW_SHOW, $main)

    While 1
        Select
        Case $openWebsiteButtonFlg = True
                _openWebsiteButtonAction()
                $openWebsiteButtonFlg = False
        EndSelect
        If Not WinExists($IE_TITLE) Then $openWebsiteButtonFlg = False ; this is strange

        Sleep(100)
    WEnd
EndFunc   ;==>_main

Func _exit()
    Exit
EndFunc   ;==>_exit

Func _openWebsiteButton()
    Switch @GUI_CtrlId
        Case $OpenWebsiteButton
            $openWebsiteButtonFlg = True
    EndSwitch
EndFunc

Func _openWebsiteButtonAction()
    If ObjName($IEHWND) = "IWebBrowser2" Then
        _IEQuit($IEHWND)
        ;If @error Then Return SetError(@error, @extended, -1)
    EndIf
    Local $url = "https://www.autoitscript.com/site/"
    _IECreate($url, 0, 1, 0)
    ;If @error Then Return SetError(@error, @extended, -1)

    Local $websiteTimer = TimerInit()
    Do
        While 1
            $aWinList = WinList("[CLASS:IEFrame]")
            For $i = 1 To $aWinList[0][0]
                If BitAND(WinGetState($aWinList[$i][1]), 2) And StringInStr(WinGetText($aWinList[$i][1]), $url) Then
                    $IEHWND = _IEAttach($aWinList[$i][1], "hwnd")
                    $IE_TITLE = WinGetTitle($aWinList[$i][1])
                    ;If @error Then Return SetError(@error, @extended, -1)
                    ExitLoop 3
                EndIf
            Next
        WEnd
    Until TimerDiff($websiteTimer) > 6000
EndFunc

Perhaps some of the error code could be useful. I don't know why it is commented out. Actually this may be a big part of the problem: errors should be checked.

Edited by czardas
Link to comment
Share on other sites

Thank you again czardas! Unfortunately, I can still make the button to stop working by closing the IE window quickly.

Further testing, I think it might have something to do with while loop, if I close the window quick enough to stop the button from functioning, the process is constantly using 25% of CPU. If I remove the while loop, it appears to be working fine even if IE window is closed quickly. But I have to use this while loop in order to use _IEAttach because the website that I am accessing only works with following method.

While 1
            $aWinList = WinList("[CLASS:IEFrame]")
            For $i = 1 To $aWinList[0][0]
                If BitAND(WinGetState($aWinList[$i][1]), 2) And StringInStr(WinGetText($aWinList[$i][1]), $url) Then
                    $IEHWND = _IEAttach($aWinList[$i][1], "hwnd")
                    $IE_TITLE = WinGetTitle($aWinList[$i][1])
                    ;If @error Then Return SetError(@error, @extended, -1)
                    ExitLoop 3
                EndIf
            Next
        WEnd

 

Edited by wuruoyu
Link to comment
Share on other sites

You must have faster fingers than me! It's strange because it seems to work sometimes, and at other times not. For some reason it seems to work if you treat it carefully. If I instantly press Alt+F4 to close the window before it has fully loaded, the script crashes and I get this in the console of SciTE:

"C:\Program Files\AutoIt3\Include\IE.au3" (2167) : ==> The requested action with this object has failed.:
Return SetError($_IESTATUS_Success, 0, HWnd($oObject.HWnd()))
Return SetError($_IESTATUS_Success, 0, HWnd($oObject^ ERROR
->22:56:48 AutoIt3.exe ended.rc:1

This is most likely because there is no error handling in your code. I'm a bit tired to figure it out right now.

Link to comment
Share on other sites

It could also be an AutoIt bug or even a Windows bug. I have a similar problem where the right and left arrow keys simply stop working after spamming the keyboard for a while, but it's hard to reproduce the behaviour consistently. The code also uses On Event message handling.

Link to comment
Share on other sites

This is my final attempt. I removed the loops from _openWebsiteAction() along with some other changes. The crash I mentioned, indicates that there is a problem with the IE UDF and needs further investigation.

#NoTrayIcon
#include <StaticConstants.au3>
#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <GuiButton.au3>
#include <EditConstants.au3>
#include <IE.au3>

Opt("GUIOnEventMode", 1)

;_IEErrorHandlerRegister(_IEErrorFunc)

Global $OpenWebsiteButton, $IEHWND ; ,$openWebsiteButtonFlg

_main()

Func _IEErrorFunc($oError)
    ConsoleWrite(@ScriptFullPath & " (" & $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.description is: " & @TAB & $oError.description & @CRLF & _
            @TAB & "err.source is: " & @TAB & @TAB & $oError.source & @CRLF & _
            @TAB & "err.helpfile is: " & @TAB & $oError.helpfile & @CRLF & _
            @TAB & "err.helpcontext is: " & @TAB & $oError.helpcontext & @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   ;==>_IEErrorFunc

Func _main()
    $main = GUICreate("main", 143, 63, -1, -1, -1, -1)
    GUISetOnEvent($GUI_EVENT_CLOSE, "_exit")

    $OpenWebsiteButton = GUICtrlCreateButton("Open Website", 20, 20, 100, 20, -1, -1)
    GUICtrlSetOnEvent(-1, "_openWebsiteButton")

    GUISetState(@SW_SHOW, $main)

    While 1
        Sleep(10)
    WEnd
EndFunc   ;==>_main

Func _exit()
    Exit
EndFunc   ;==>_exit

Func _openWebsiteButton()
    Switch @GUI_CtrlId
        Case $OpenWebsiteButton
            _openWebsiteButtonAction()
    EndSwitch
    ; $openWebsiteButtonFlg = False
EndFunc

Func _openWebsiteButtonAction()
    If ObjName($IEHWND) = "IWebBrowser2" Then
        _IEQuit($IEHWND)
        If @error Then Return SetError(@error, @extended, -1)
    EndIf
    Local $url = "https://www.autoitscript.com/site/"
    _IECreate($url, 0, 1, 0)
    If @error Then Return SetError(@error, @extended, -1)

    ;Local $websiteTimer = TimerInit()
    ;Do
    ;    While 1
            $aWinList = WinList("[CLASS:IEFrame]")
            For $i = 1 To $aWinList[0][0]
                If BitAND(WinGetState($aWinList[$i][1]), 2) And StringInStr(WinGetText($aWinList[$i][1]), $url) Then
                    $IEHWND = _IEAttach($aWinList[$i][1], "hwnd")
                    If @error Then Return SetError(@error, @extended, -1)
                    ExitLoop ;3
                EndIf
            Next
    ;    WEnd
    ;Until TimerDiff($websiteTimer) > 6000
EndFunc

When the window was closed too quickly, you were getting stuck in the while loop because the window could no longer be found. I think it's that simple.

Edited by czardas
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...