Jump to content

controlsend to a pop up


anandnz
 Share

Recommended Posts

Hi

I am trying to split the code into many functionalities. one such is this. If this works, i will integrate into major program.

I thought i got this working in other area. Now i am using the same logic to close a pop up dialog box, similar code with no success.

Please advice.

#include <WinAPI.au3>
#include <File.au3>
Opt('WinTitleMatchMode', 2)
_Main()
Func _Main()
    Local $aWindows, $i; $text
    $aWindows = _WinAPI_EnumWindows()
    Local $OutStg
    For $i = 1 To $aWindows[0][0]
        Local $Wclass = $aWindows[$i][1]
        Local $Wtitle = WinGetTitle($aWindows[$i][0])
        if $Wclass = "#32770" And $Wtitle = "Error" Then
            $OutStg = $Wtitle &   $Wclass
            ControlGetFocus("[TITLE:Error; CLASS:#32770]")
            ConsoleWrite(" got a error ......" & @CRLF)
            ;_handlepop($Wtitle,$Wtext)
            _handlepop()
            ConsoleWrite("The window details are " & $OutStg & @CRLF)
        ;_FileWriteLog($logpath, $OutStg)
        ;ConsoleWrite("Item " & $i & " of " & $aWindows[0][0], $text)
        EndIf
    Next
EndFunc   ;==>_Main
;Func _handlepop($title, $string)
Func _handlepop()
        ConsoleWrite(" Inside handlepop ......" & @CRLF)
        ControlGetFocus("[TITLE:Error; CLASS:#32770]")
        ControlSend ("[TITLE:Error; CLASS:#32770]", "", "", "{ENTER}"); command to close it
        Return
EndFunc

It detects the pop up open in the system, The message inside the handlepop() is seen in the console, however the the pop up does not close.

Any help will be appreciated.

Thanks and Regards

-- Anand

Edited by anandnz
Link to comment
Share on other sites

You're using ControlGetFocus does nothing but return the CLASSNN of the control that has the focus. You're not using the return value, so it realy doesn't do anything.

I think you meant to use ControlFocus, but that requires you to have a way to identify the control you want to send enter to and if you have that, you could just use that in the ControlSend function.

First thing to try would be to check the CLASSNN of the button you want to interact with using the au3info tool and using that with ControlClick, ControlSend, or ControlCommand.

Another option would be to send a key combination in the button has one assigned to it. (usually Alt + underline letter in buttontext)

Lastly the control could be made to resist automation. In this case the first set is to make sure the window you interact with is active, but after that it's basically trial and error. I have noticed sending space to such controls often works.

Link to comment
Share on other sites

[/autoit]  Thank you Tvern for the message.  I am looking for this help....
Is there a way to know if the application has completed running in run command. My program run indefinetly when it encounters a error scenario, i currently handle by a seperate function in the while loop. Same behaviour when i call with AdlibRegister().

Here is problem:

$pid = Run( Third party executable ) ; It runs on its own until activity is completed, i have no control. Note: This process takes off the license, i hold .. 

I handle the error messages by seperate function, either called by AdlibRegister or in a while loop to constantly check for errors. However, after exiting the third party application while closing the dialog box. my program run indefinetly somewhere  ( i do not know how to put a break command here)

i tried the following .. 
1. If processexists() ; did not work
2. hardcoded 3-4 iterations to break the loop ; did not work..  any advice please ..
[autoit]#include <File.au3>
#include <Array.au3>
#include <Timers.au3>

Local $passlog = "c:\AutoIT_Script_documents\Publishlogs\passlog\Passlog.txt"
Local $faillog = "c:\AutoIT_Script_documents\Publishlogs\faillog\faillog.txt"
Local $common = "c:\AutoIT_Script_documents\Publishlogs\scripts"
Local $killall = "c:\AutoIT_Script_documents\Publishlogs\scripts\kill_all.bat"
Local $passflg = 1
Local $failflg = 1

Func _handleErrorMsg()

       WinWait("Error","",20)
        If WinExists("Error") Then ; This is successful completion window and needs a user to close it
           ControlGetFocus("Error","Failed to load defin")
           ControlSend ("[TITLE:Error; CLASS:#32770]", "", "", "{ENTER}"); command to close it
           ConsoleWrite("I have closed the dialog box 1 " & @CRLF)
       EndIf
EndFunc
; The below array controls all the scripts, batchfile to copy at one place.
;Any addition of new template for document publication has to be done here by adding a row ( make sure increase the row array and add a row.
;There is no sequence, but index is usually run in the end of the files obviously.
; Do not use winactive commands as they do not work when system is locked. bummer spent a long time to replace them
; A lot of iterations of testing needed to find all the possible windows to handle.
;
if FileExists($passlog) then FileDelete($passlog)

if FileExists($faillog) then FileDelete($faillog)
Local $Scripts[10][4] = [["a",$common & "b.bat", 50000, True], _
                   ["b",$common & "b.bat", 500000, True], _
                ["c",$common & "c", 500000, True], _
                   ["d",$common & "d.bat",50000,True], _
                   ["e",$common & "e.bat",50000,True], _
                   ["f",$common & "f.bat",50000,True], _
                   ["g",$common & "g.bat",50000,True], _
                   ["h",$common & "h.bat",50000,True], _
                   ["i",$common & "i.bat",50000,True], _
                   ["j",$common & "j.bat",50000,True]]

;_ArrayDisplay($Scripts); Enabling this will have all the listing in the spread sheet.
For $cnt = 0 To UBound($Scripts) - 1
    If $Scripts[$cnt][3] Then
        ;local $runtime = Run($killall) ; Ensure all applications are closed and temporary files deleted, "This if the control comes here breaking frm loop"
        ;Local $current_Time = TimerInit()
        Global $FileProcessing = $Scripts[$cnt][0]
        Global $break_time = $Scripts[$cnt][2]
        Global $batchfile = $Scripts[$cnt][1]
        Global $DocPub = 1
        Global $handle = 0
        Global $PID = 0

        AdlibRegister("_handleErrorMsg", 4000)

        $officeSuccess = 0
        $DocTimer = 1
        ;ConsoleWrite("The batch file is " & $Scripts[$cnt][1] & @CRLF)
        ;ConsoleWrite("The Maximum Time out is " & $Scripts[$cnt][2] & @CRLF)
        Run("set PATH=C:\Program Files\openfile\bin\exe\win32pc;%PATH%") ; Run once this command to set the path. Actually not needed if the system is already set with path.
        ;Storing the big string in the command variable so that i can run this whole string .. this comamnd from openfile is not yet explored.
        $command = "C:\Program Files\openfile\bin\exe\win32pc\" & "openfile.exe -file " & $Scripts[$cnt][0]
        ConsoleWrite("The break time is " & $break_time & @CRLF)
        sleep(50)
        Run($command) ; working hurray ! Yeah .. the openfile command works
        $APP_PID = Run($command) ; working hurray ! Yeah

        WinWait("Information","",$break_time)
        ControlFocus("Information", "text", "" )
        If WinExists("Information") Then ; This is successful completion window and needs a user to close it
           ControlSend ("[TITLE:Information; CLASS:#32770]", "", "", "{ENTER}"); command to close it
            _FileWriteLog($passlog, "File " & $Scripts[$cnt][0] & "------ PASS")
            sleep(4000)
            Run($batchfile)
            sleep(4000)
            $DocPub = 0
        EndIf

        If $DocPub == 1 Then
           _FileWriteLog($faillog, "File " & $FileProcessing & "------ FAIL")
           Run($killall) ; Ensure all applications are closed and temporary files deleted
        EndIf
    Else
        ConsoleWrite("This file is not selected ... " & $FileProcessing & @CRLF)

    EndIf
Next; Yeah ready for next cycle

I tried to call AdlibUnRegister() but just could not resolve this issue.

Though all the error messages are closed, the control is still goes in above loop forever prints to console "I have closed the dialog box 1".

Thanks in advance

-- Anand

Edited by anandnz
Link to comment
Share on other sites

ProcessExist() should be the way to go, but I think something else (like declaring $PID in a loop) is messing it up. I have to go out for an hour, but will have a look when I'm back.

I have also tried to break with timer in vain.. When i use exit, it works but that is not what i want .. i want to continue the FOR loop (see above)

For $cnt = 0 To UBound($Scripts) - 1
. Any help is appreciated.

Func _handleErrorMsg()

        local $rettimer
        Local $timdata = 6000
           WinWait("Error","",20)
        If WinExists("Error") Then ; This is successful completion window and needs a user to close it
           ControlGetFocus("Error","Failed to load defin")
           ControlSend ("[TITLE:Error; CLASS:#32770]", "", "", "{ENTER}"); command to close it
           ConsoleWrite("I have closed the dialog box 1 " & @CRLF)
    EndIf
        $rettimer =_checktimer($timdata)
        if $rettimer == "Expired" Then
            AdlibUnRegister("_handleErrorMsg")
            ;Exit
        EndIf

EndFunc

Func _Checktimer($timdata)
    Local $timdiff
    $timdiff = TimerDiff($begin)
    if $timdiff >= $timdata Then
        return "Expired"
    EndIf
EndFunc
Edited by anandnz
Link to comment
Share on other sites

I've gone through the script and there where a lot of potential issues. Some where more serious than others.

I've commented pretty much everything I changed, or that I think needs fixing. The most important changes where:

* taking AdlibRegister() out of the loop

* adding a "\" to the script path.

* setting CtrlID's for your ControlSend, although those need to be checked.

I don't think this script will work for you right away as I had to make a lot of assumptions about the nature of the external files you where executing and the windows you are interacting with, but you should be able to get this working.

#include <File.au3>
#include <Array.au3>
#include <Timers.au3>

;   I changed variable names to reflect the datatype they hold.
;   Changed Local to Global.
;   Moved all variable declaration to the top of the script.
Global $sPassLogPath = "C:\AutoIT_Script_documents\Publishlogs\passlog\Passlog.txt"
Global $sFailLogPath = "C:\AutoIT_Script_documents\Publishlogs\faillog\faillog.txt"
Global $sKillAllPath = "C:\AutoIT_Script_documents\Publishlogs\scripts\kill_all.bat"

;   there seemed to be a "\" missing here, so I added it.
Global $sScripsPath = "C:\AutoIT_Script_documents\Publishlogs\scripts\"

;   keep in mind this misses the trailing "\" when concatenating. (Intentional)
Global $sOpenFilePath = "C:\Program Files\openfile\bin\exe\win32pc"

;   took these declarations out of the loop and put em all together here.
Global $sFileProcessing, $iBreak_Time, $sBatchFile

;   The below array controls all the scripts, batchfile to copy at one place.
;   Any addition of new template for document publication has to be done here by adding a row ( make sure increase the row array and add a row.
;   There is no sequence, but index is usually run in the end of the files obviously.
;   Do not use winactive commands as they do not work when system is locked. bummer spent a long time to replace them
;   A lot of iterations of testing needed to find all the possible windows to handle.
Global $avScripts[10][4] = _
        [["a", $sScripsPath & "b.bat", 50000, True], _ ;    Are you sure you want $iBreak_Time to be 50 seconds?
        ["b", $sScripsPath & "b.bat", 500000, True], _ ;    Are you sure you want $iBreak_Time to be over 8 minutes?
        ["c", $sScripsPath & "c", 500000, True], _ ;    Doesn't this program have an extention?
        ["d", $sScripsPath & "d.bat", 50000, True], _
        ["e", $sScripsPath & "e.bat", 50000, True], _
        ["f", $sScripsPath & "f.bat", 50000, True], _
        ["g", $sScripsPath & "g.bat", 50000, True], _
        ["h", $sScripsPath & "h.bat", 50000, True], _
        ["i", $sScripsPath & "i.bat", 50000, True], _
        ["j", $sScripsPath & "j.bat", 50000, True]]

If FileExists($sPassLogPath) Then FileDelete($sPassLogPath)
If FileExists($sFailLogPath) Then FileDelete($sFailLogPath)

;   Took this out of the loop.
;   If you put this inside a loop that ends before the time is up, it will never be called. Also 4000 ms seems long. I'd use <500
AdlibRegister("_handleErrorMsg", 4000)

;   Run once this command to set the path. Actually not needed if the system is already set with path.
;   I'm not familliar with how set works. Wouldn't this add the string each time you run this, resulting in lots of duplicates?
;   Perhaps it's wise to first check the current value of set.
Run("set PATH=" & $sOpenFilePath & ";%PATH%")


;_ArrayDisplay($avScripts); Enabling this will have all the listing in the spread sheet.
For $iCnt = 0 To UBound($avScripts) - 1
    ;   I try to keep few lines between If and Endif for readability.
    ;   This should function the same as the old setup where all the code was embedded in a big If statement.
    If Not $avScripts[$iCnt][3] Then
        ConsoleWrite("This file is not selected ... " & $sFileProcessing & @CRLF)
        ContinueLoop
    EndIf

    ;   You could also use the array directly, but this does make it more clear, so I'll leave it.
    ;   Moved variable declaration to the top though.
    $sFileProcessing = $avScripts[$iCnt][0]
    $sBatchFile = $avScripts[$iCnt][1]
    $iBreak_Time = $avScripts[$iCnt][2]
    $sCommand = $sOpenFilePath & "\openfile.exe -file " & $sFileProcessing

    ;ConsoleWrite("The batch file is " & $avScripts[$iCnt][1] & @CRLF)
    ;ConsoleWrite("The Maximum Time out is " & $avScripts[$iCnt][2] & @CRLF)
    ConsoleWrite("The break time is " & $iBreak_Time & @CRLF)

    Run($sCommand) ;    You where running the same command twice, and not using the PID of either one.

    $hWnd = WinWait("Information", "", $iBreak_Time)

    ;   If WintWait returns a handle, we already know the window exists, no need to use WinExists().
    If Not $hWnd Then
        _FileWriteLog($sFailLogPath, "File " & $sFileProcessing & "------ FAIL")
        ;       Run($sKillAllPath) ; Ensure all applications are closed and temporary files deleted
        ;       RunWait is probably better than Run for this.
        ;       Could you not create a function for the job of this batch file?
        RunWait($sKillAllPath)
        ContinueLoop
    EndIf

    ;this is just a guess, but you'll need the CtrlID you want to interact with, unless it has the focus by default. Use au3Info to get the ctrlid.
    ControlSend($hWnd, "text", "[CLASSNN:Button1]", "{ENTER}") ;Try adding a ControlID here.
    _FileWriteLog($sPassLogPath, "File " & $sFileProcessing & "------ PASS")
    ;   Sleep(4000)
    ;   Run($sBatchFile)
    ;   Sleep(4000)
    ;   Would this be better than the above three lines?
    RunWait($sBatchFile)
Next

Func _HandleErrorMsg()
    ;WinWait is not needed here. Just call WinExists more often.
    Local $hWnd = WinExists("[TITLE:Error; CLASS:#32770]")
    If $hWnd Then ; This is successful completion window and needs a user to close it

        ;Does this ever show up when the PopUp shows? If not, then the description of the window is incorrect.
        ConsoleWrite("Dialog box 1 was found! Trying to close. " & @CRLF)

        ;this is just a guess, but you'll need the CtrlID you want to interact with, unless it has the focus by default. Use au3Info to get the ctrlid.
        If ControlSend($hWnd, "", "[CLASSNN:Button1]", "{ENTER}") Then

            ;does this ever show up, and if so, does the dialog box actually close?
            ConsoleWrite("I have closed the dialog box 1 " & @CRLF)
        Else
            ConsoleWrite("I closing dialog box 1 failed." & @CRLF)
        EndIf
    EndIf
EndFunc
Link to comment
Share on other sites

Hi Tvern,

Much appreciated for a useful review comments. I haven't yet cleaned up and usually i am messy with the names until i get it working. Bad habits.

Your all comments are relevant. I changed the naming, AdlibRegister()out of the loop.

Yes the description of the error pop message is wrong.. I have corrected it.

I assure you, that i used Run() only once. but while copying to the lesser prototype here, i got it wrong. ( i actually cannot use Run twice because of license !)

Information: The thirdparty application i run is a massive document publisher.. when it is running, i have no control of it except to kill it when i have errors.

and act on their flawed design of prompting the user to close dialog boxes which they keep throwing up log it and continue with next file generation.

Error messages: I have this issue, when the document i want to print doesn't exist it throws up

1. _WinWaitActivate("Error","Failed to load defin") immediately followed by _WinWaitActivate("Error","Error opening word d")

Note: I have this from the recorder. I cannot use _WinWaitActivate as my scripts need to work when virtual server goes idle and screen lock.

So when i changed to

If Controlsend("Error","","","{ENTER}")
Then instead of
If ControlSend($hWnd, "", "", "{ENTER}")
in the function

Func _handleErrorMsg(), i could able to close the error messages. However, after closing the error messages, It is in infinite loop here. what i would actually do is to print the culprit "file" in log and continue with the loop.

2.

$hWnd = WinWait("Information", "",[b] $iBreak_Time[/b])
does not work do not know why.

I also want another timer to run in parallel, if success or fail with error messages, this is a insurance of my scripts working when i get unhandled error boxes.

I can log the file, as timed out and continue with the for loop.

So 2 steps away from decent version to install which is timer expiry working .. and this logic to handle error messages. Any help is appreciated, as i try a conditional break with adlibunregister()

Thanks a ton.

Regards

-- Anand

1.

$hWnd = WinWait("Information", "", $iBreak_Time)
        ConsoleWrite("The break time is: " &$iBreak_Time & @CRLF)
The WinWait does not work. Edited by anandnz
Link to comment
Share on other sites

So 2 steps away from decent version to install which is timer expiry working ..

I'm not sure what part of the script you want to have a timeout, as there where several blocking functions in the original script. Could you be more specific?

and this logic to handle error messages.

If with that you mean logging found windows and actions taken, then it shouldn't be hard to implement once the script works well, which I would focus on first.

Any help is appreciated, as i try a conditional break with adlibunregister()

The _HandleErrorMsg() function should return directly if there is nothing for it to do, so it shouldn't cause any interference with your script.

I guess it still isn't closing the popups properly, causing it to try over and over untill the popup is manually closed. Focus on debugging the function rather than stopping the function from being called.

The WinWait does not work.

Define "does not work" does it return directy where you don't expect it to, does it return the wrong hWnd, or does it wait untill the timeout is reached?

Try adjusting "Information" to something more specific using au3info and make sure the title of the window doesn't have any spaces before it. You could also try setting "Opt("WinTitleMatchMode",2)".

Link to comment
Share on other sites

Hi Tvern

Thank you again..

I'm not sure what part of the script you want to have a timeout, as there where several blocking functions in the original script. Could you be more specific?

Time out should ideally run when i start the Run( ) command. If i cannot get the document within certain time, i should just log the file and go to next iteration.

secondly a second timer, i am attempting is when i get error pop up message, timer with a very short duration so that, if error handling fails, atleast this timer should let me continue the loop.

Please can you point me to blocking calls/functions, i should be avoiding it.

If with that you mean logging found windows and actions taken, then it shouldn't be hard to implement once the script works well, which I would focus on first.

The _HandleErrorMsg() function should return directly if there is nothing for it to do, so it shouldn't cause any interference with your script.

I guess it still isn't closing the popups properly, causing it to try over and over untill the popup is manually closed. Focus on debugging the function rather than stopping the function from being called.

Yes once i changed the code

Func _handleErrorMsg()

    Local $hWnd = WinExists("[TITLE:Error; CLASS:#32770]")
    ConsoleWrite("The value of Return Handle is : "& $hWnd  & @CRLF)
    If Not $hWnd Then ; If errror pop ups, handle them by feeding ok ..   ( I made this change to force return )
        return
    ;Does this ever show up when the PopUp shows? If not, then the description of the window is incorrect. 
        ConsoleWrite("Dialog box 1 was found! Trying to close. " & @CRLF)
    ;this is just a guess, but you'll need the CtrlID you want to interact with, unless it has the focus by default. Use au3Info to get the ctrlid.
        ConsoleWrite("I still have handle to HandleErrorMsg() loop " & @CRLF)
        ControlGetFocus("Error")
        If Controlsend("Error","","","{ENTER}") Then
        ;If ControlSend($hWnd, "", "", "{ENTER}") Then
            ;does this ever show up, and if so, does the dialog box actually close?
            ConsoleWrite("I have closed the dialog box 1 " & @CRLF)
        Else
            ConsoleWrite("I closing dialog box 1 failed." & @CRLF)
            return
        EndIf
    EndIf

EndFunc

Here is the output ..

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

--- Here i have manually cleared the pop ups ... and rightly picked up by the code.

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

With the change i made above even though the $hWnd exists, it is not going to control send...

what i do not understand is the with the code i put here before, it closes the pop ups and continues stay in the function .. what am i missing ..

Define "does not work" does it return directy where you don't expect it to, does it return the wrong hWnd, or does it wait untill the timeout is reached?

Try adjusting "Information" to something more specific using au3info and make sure the title of the window doesn't have any spaces before it. You could also try setting "Opt("WinTitleMatchMode",2)".

No control stays put in the Func _handleErrorMsg(), when i run the fail document.. Success part is ok, no probs. I use the setting "Opt("WinTitleMatchMode",2)".

It's too late here, i go home, i will attempt your suggestions tomorrow. Thanks a ton.

PS: I had faced this problem earlier, and only way it was resolved is by adlibunregister() ...I will try tomorrow to under the no return of $hWnd. ??

Thanks and Regards

-- Anand

Edited by anandnz
Link to comment
Share on other sites

Here is the output ..

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

The value of Return Handle is : 1

--- Here i have manually cleared the pop ups ... and rightly picked up by the code.

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

The value of Return Handle is : 0

I screwed up there. Most Win... functions return a handle on success. WinExists does not.

No control stays put in the Func _handleErrorMsg(), when i run the fail document.. Success part is ok, no probs. I use the setting "Opt("WinTitleMatchMode",2)".

Ah. it doesn't get stuck in the function. It just calls it all the time. Just don't put consolewrites before the check if a handle was returned.

Here are my suggested changes.

Func _handleErrorMsg()
    Local $hWnd = WinGetHandle("[TITLE:Error; CLASS:#32770]")
    If Not $hWnd Then Return ;While the function will be called all the time, it won't do anything unless a matching window is found. The rest of the script will continue to function.
    ConsoleWrite("The value of Return Handle is : "& $hWnd  & @CRLF)
    ConsoleWrite("Dialog box 1 was found! Trying to close. " & @CRLF)
    ConsoleWrite("I still have handle to HandleErrorMsg() loop " & @CRLF)
    ControlGetFocus("Error")
    If Controlsend("Error","","","{ENTER}") Then
        ConsoleWrite("I have closed the dialog box 1 " & @CRLF)
    Else
        ConsoleWrite("I closing dialog box 1 failed." & @CRLF)
    EndIf
EndFunc
Edited by Tvern
Link to comment
Share on other sites

Hi Tvern,

Tried the new code, unfortunately no change, control doesn't return ..

What i did not understand in my last post is "$hWnd" is true (1) why did not go inside the loop ?

Trying to get rid of Adlibregister() and use while 1 with conditions.. any ideas are appreciated.

Thanks in Advance

-- Anand

Link to comment
Share on other sites

What i did not understand in my last post is "$hWnd" is true (1) why did not go inside the loop ?

In your example it will have gone inside the loop, but you had "Return" on the first line, so it's not going to do anything.

In my last example it will have been in the loop if you saw any of the consolewrites. When it doesn't go in the loop. nothing shows.

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