OldMike Posted October 16, 2010 Share Posted October 16, 2010 Clued into AutoIT by a colleague at Experts Exchange and have found it to be a great upgrade from VBScripts. My need is pretty basic, but just can't seem to get it going. I need to launch four separate instances of an application (ABBYY OCR program), which I have been able to do just fine. I think I am also able to capture what the PID is when it launches. Each time I launch I send a few key strokes to select a canned macro from within the application; also working fine. But later on I need to be able to regain focus of a specific instance and do a few more key strokes to shut it down; that I cannot do. I don't know if I need to name each window with a unique name (have not been able to set a new title) and the refer to the name to get control back (how?) or, since I have the PID how do I get the keystrokes to go to the specific process I want? Would REALLY appreciate some explicit lines of code, or just send me to a sample program that opens, then minimizes, then regains control of a Windows app. What I have so far: $PID1 = run ("C:\Program Files (x86)\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,"") send ("n") send ("^t") send ("{ENTER}") I assume $PID1 (then $PID2 when I open another session) is the PID or handle(?) that can be used later to select this instance. Mike Link to comment Share on other sites More sharing options...
Realm Posted October 17, 2010 Share Posted October 17, 2010 (edited) Hello OldMike,Welcome to the AutoIt Forums First, pid is an abbreviation for Process ID. However in your example you are using the abbreviation as a variable, being in which you could name that variable anything you like with a few limitations, which you can read more about variables and declaring them here if you wish.With the Function Run, it returns the actual pid. With that said, you could use $oldMike = Run(), and the actual pid would be assigned to $oldMike.To have 4 different instances of the same program, it would be wise to declare a different variable to each Run. You can use $pid1, $pid2, and so on. You could use $abby1, $abby2, to help remind you of the process name. To Automate, Close, or Call a particular instance of the Program you are running, you would call it by its individual variable, such as ProcessClose($abby2).Hope this helps RealmEdit: Fixed typos, and provided a link to Language Reference - Variables in the online help file. Edited October 17, 2010 by Realm My Contributions: Unix Timestamp: Calculate Unix time, or seconds since Epoch, accounting for your local timezone and daylight savings time. RegEdit Jumper: A Small & Simple interface based on Yashied's Reg Jumper Function, for searching Hives in your registry. Link to comment Share on other sites More sharing options...
OldMike Posted October 17, 2010 Author Share Posted October 17, 2010 Thanks; very helpful. I have been able to change the title, then make Send go to the correct window. I do not need to use ProcessClose now, because if I can successfully get Send to go to the correct session I can use keystrokes to shut the program down gracefully. However I have seen some strange behavior, plus my method is fragile. Strange: if I launch the programs with {@SW_MAXIMUM) I can see the titles change. So to test I launch the first ABBYY as TEST1, and the second as TEST2 and the window title changes. I can then activate TEST1 and Send to it successfully, but when I do the TITLE2 changes back to original, but it will still respond to an activation of TEST2. So the title change-back seems to just be cosmetic. Does that make sense? (I hate stuff that 'just happens' rather than I understand it). Fragile: I can launch the script and then both ABBYY sessions launch and run and shut down, but only if I stay quiet. If I should open Windows Explorer to watch the folders holding the PDF the Send commands start going to the open window, making for some bazaar behavior. So the two windows are independently controllable so long as nothing else happens, but if another window opens independent of the script the Send command goes to the new window, not the one I think I am addressing. How can I assure that it goes where I want? Would SendKeepAlive override the Windows Explorer window? Link to comment Share on other sites More sharing options...
Realm Posted October 18, 2010 Share Posted October 18, 2010 (edited) Hello OldMike,It's really difficult to help you, without seeing your script or at least and example of it. My best educated guess would be that your right, it's just cosmetic as long as you can still call it by your custom title. However I am assuming that your trying to use ControlSend() with the $pid as ControlSend($pid,'',). If this is the case, the various Control functions do not use PID to call, they perform with Handles or Window Titles. So with that in mind, This is how I obtain the handles of each instance, while changing the title of the window at that same time. This example also shows how to use the handles in the control functions. *Note - You will have to change the Window Titles 'ABBYY' that I had assigned, to the real Title name. If you don't know the actual title name, it can be obtained with the Au3Info.exe application found in your AutoIt3 Installation Folder.Local $abby_Handles[4] For $a = 0 To 3 Run("C:\Program Files (x86)\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,"") WinWaitActive('ABBYY','') WinSetTitle('ABBYY','','Test' & $a) $abby_Handles[$a] = WinGetHandle('Test' & $a,'') Next ControlSend($abby_Handles[0],'','Edit1','Send something to the first instance of abby') ControlSend($abby_Handles[1],'','Edit1','Send something to the second instance of abby') ControlSend($abby_Handles[2],'','Edit1','Send something to the third instance of abby') ControlSend($abby_Handles[3],'','Edit1','Send something to the fourth instance of abby') However, you don't need to create a new Title for a window in order to call on it later, unless that is for your own cosmetic reasons. Run all 4 instances and then use WinList() to obtain each instances handles.*Note - You will have to change the Window Titles 'ABBYY' that I had assigned, to the real Title name. If you don't know the actual title name, it can be obtained with the Au3Info.exe application found in your AutoIt3 Installation Folder.Local $abby_Handles For 1 To 4 Run("C:\Program Files (x86)\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,"") Next Do $abby_Handles = WinList('ABBYY','') ;might want to create a timeout check incase of errors Until $abby_Handles[0][0] = 4 ;keeps checking until 4 instances of Abby are present ControlSend($abby_Handles[1][1],'','Edit1','Send something to the first instance of abby') ControlSend($abby_Handles[2][1],'','Edit1','Send something to the second instance of abby') ControlSend($abby_Handles[3][1],'','Edit1','Send something to the third instance of abby') ControlSend($abby_Handles[4][1],'','Edit1','Send something to the fourth instance of abby')RealmEdit: Fixed some typos, and my error inside the second example while checking for 4 instances. Edited October 18, 2010 by Realm My Contributions: Unix Timestamp: Calculate Unix time, or seconds since Epoch, accounting for your local timezone and daylight savings time. RegEdit Jumper: A Small & Simple interface based on Yashied's Reg Jumper Function, for searching Hives in your registry. Link to comment Share on other sites More sharing options...
OldMike Posted October 18, 2010 Author Share Posted October 18, 2010 Wow; great help. I've done a lot with VBScript, but just now dabling with AutoIT. I only changed the title because I thought I needed that for addressing later on. A couple of new questions now: 1. You mention addressing using the handles to send control commands. But what I want to send is keys (Send); is that considered a control? I don't see anything on the Send documentation about first getting focus. 2. The result I have so far is that I can get focus/activation on demand, with a twist. If I launch four sessions and set back it will run fine and randomly gain control and shut down any given session and restart. But if I have something else open, such as Windows Explorer, the Send commands go to the open Windws Explorer window. So it appears that the addressing works but is fragile, not top tier. So I need a method that will grant focus to what I want no matter what else might be open beforehand. 3. Making a list of handles is not useful for me (I think) because though I might start them all in order at boot up, thereafter they are random. Some will finish before others (which I can detect), in which case I shut down the one that finished (not by forced shut down; I want to get control of the selected one and send the key strokes that will gracefully shut it down) and then start it from scratch. SO I have to know specifically which session (they each run a different macro) is associated with which handle. Link to comment Share on other sites More sharing options...
OldMike Posted October 18, 2010 Author Share Posted October 18, 2010 (edited) Here's my code. Doesn't do everything I need to do, just testing ability to launch and shut down. expandcollapse popup;==== Manage A Single ABBYY session, watching P1, PDF1, and OCR1 Local $WatchIn = "D:\P" Local $MoveTo = "D:\PDF" Local $WatchOut = "D:\OCR" Local $UpBucket = "D:\Reg Out\" Local $ABBYY_Active Local $First_AB = 1 Local $Last_AB = 4 Local $InCount ;== Find the number of PDFs in WatchIn waiting For $n = $First_AB to $Last_AB $size = DirGetSize(($WatchIn & $n &"\"),1) ; Get count of PDFs to be processed $ABBYY_Active = "ABBYY" & $n $ABBYY_Active = run ("C:\Program Files (x86)\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,"") Sleep (5000) Send("n") Send("^t") Select Case $n=1 $n=1 ;NOOP Case $n=2 Send("{DOWN}") Case $n=3 Send("{DOWN}") Send("{DOWN}") Case $n=4 Send("{DOWN}") Send("{DOWN}") Send("{DOWN}") EndSelect Send("{ENTER}") Next Sleep (5000) For $n = $First_AB to $Last_AB $ABBYY_Active = "ABBYY" & $n WinActivate($ABBYY_Active) Send("!f") Send("x") Send("n") Next Edited October 18, 2010 by OldMike Link to comment Share on other sites More sharing options...
Realm Posted October 18, 2010 Share Posted October 18, 2010 (edited) Hello OldMike1) Obtaining Focus from a control function works with most windows, however there are an occasional window that needs to be activated before sending a control, if you find this to be situation than a simple WinActivate() should do the trick, or just to be safe, you could activate the individual window, with the same handles WinActivate($abby_Handles[1][1],'')To send keys, you can look up how to send key reference in the Help File under function Send(), Edit: I wrote this before I was aware that was what your were using, I assumed you were using ControlSend()2) OK, evidently you will have to bring this application into focus by using WinActivate() before using the control functions, if you still are having a problem, then try bringing the control into focus with ControlFocus(). If still at loss, the application might be resistant to Automation.3) The $handles are created in the array that I gave an example to in each script.Here is a problem with your script:$ABBYY_Active = "ABBYY" & $n ; you have assigned the name 'ABBYY' & $n, but $ABBYY_Active = run ("C:\Program Files (x86)\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,""); here that gets changed to the PID of the programIf This is referencing a File Menu in the applicationSelect Case $n=1 $n=1 ;NOOP Case $n=2 Send("{DOWN}") Case $n=3 Send("{DOWN}") Send("{DOWN}") Case $n=4 Send("{DOWN}") Send("{DOWN}") Send("{DOWN}") EndSelectThen you might want to look at WinMenuSelectItem() in the HelpFileNot inlcuding WinMenuSelectItem, This is how you should have it:expandcollapse popup;==== Manage A Single ABBYY session, watching P1, PDF1, and OCR1 Local $WatchIn = "D:\P" Local $MoveTo = "D:\PDF" Local $WatchOut = "D:\OCR" Local $UpBucket = "D:\Reg Out\" Local $ABBYY_Active Local $First_AB = 1 Local $Last_AB = 4 Local $InCount Local $Abbyy[$Last_AB] ;== Find the number of PDFs in WatchIn waiting For $n = $First_AB to $Last_AB $size = DirGetSize(($WatchIn & $n &"\"),1) ; Get count of PDFs to be processed $ABBYY_Active[$n] = run ("C:\Program Files (x86)\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,"") WinWait($ABBYY_Active[$n]) ;removed the sleep, and added a specific window wait Send("n") Send("^t") Select Case $n=1 $n=1 ;NOOP Case $n=2 Send("{DOWN}") Case $n=3 Send("{DOWN}") Send("{DOWN}") Case $n=4 Send("{DOWN}") Send("{DOWN}") Send("{DOWN}") EndSelect Send("{ENTER}") Next Sleep (5000) For $n = $First_AB to $Last_AB WinActivate($ABBYY_Active[$n]) Send("!f") Send("x") Send("n") Next [size=2]To close a given instance of Abbyy, then use WinClose($ABBYY_Active[$n])Thanks for putting your code into AutoIt Tags, it makes it a lot more readable.See if that last example does more of what you need, However, if you are planning to use your pc while that is running, you might want to look into ControlSend() which does not utilize your mouse and keyboard.RealmEdit: My example will error, I was trying to use PID as Window Handles, give me a moment to correct and repost. I am downloading Abbyy now, so I can understand more of what your attempting to accomplish, give me a bit to play with it. Edited October 18, 2010 by Realm My Contributions: Unix Timestamp: Calculate Unix time, or seconds since Epoch, accounting for your local timezone and daylight savings time. RegEdit Jumper: A Small & Simple interface based on Yashied's Reg Jumper Function, for searching Hives in your registry. Link to comment Share on other sites More sharing options...
Realm Posted October 18, 2010 Share Posted October 18, 2010 Hello OldMike, After playing around with abby, I believe I have a working test script for you: expandcollapse popup;==== Manage A Single ABBYY session, watching P1, PDF1, and OCR1 Local $WatchIn = "D:\P" Local $MoveTo = "D:\PDF" Local $WatchOut = "D:\OCR" Local $UpBucket = "D:\Reg Out\" Local $ABBYY_Active Local $First_AB = 1 Local $Last_AB = 4 Local $InCount Local $Abbyy[$Last_AB] ;== Open Abby and obtain handles. For $a=1 To 4 Run("C:\Program Files\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,"") Next Do $ABBYY_Active = WinList("ABBYY FineReader 10",'') ;might want to create a timeout check incase of errors Until $ABBYY_Active[0][0] = 4 ;keeps checking until 4 instances of Abby are present Sleep(2000) ;== Find the number of PDFs in WatchIn waiting For $n = $First_AB to $Last_AB ;~ $size = DirGetSize(($WatchIn & $n &"\"),1) ; Get count of PDFs to be processed WinActivate($ABBYY_Active[$n]) Sleep(250) Send("^n") Sleep(250) Send("^t") Sleep(250) Select Case $n=1 ControlClick('Automation Manager', '', 'SysListView321', 'left', 1, 27, 11) ;selects Convert PDF/Imageas to Microsoft Word Case $n=2 ControlClick('Automation Manager', '', 'SysListView321', 'left', 1, 27, 28) ;selects Convert Photo to Microsoft Word Case $n=3 ControlClick('Automation Manager', '', 'SysListView321', 'left', 1, 27, 44) ;selects Scan to Image File Case $n=4 ControlClick('Automation Manager', '', 'SysListView321', 'left', 1, 27, 61) ;selects Scan to Microsoft Excel EndSelect Sleep(250) ControlClick('Automation Manager', '','Button2','left') Next Sleep (5000) For $n = $First_AB to $Last_AB WinClose($ABBYY_Active[$n]) Next give it a shot, and let me know if it is working for you. Did you notice how the array stores the handles, and how they are called as needed throughout the script? Realm My Contributions: Unix Timestamp: Calculate Unix time, or seconds since Epoch, accounting for your local timezone and daylight savings time. RegEdit Jumper: A Small & Simple interface based on Yashied's Reg Jumper Function, for searching Hives in your registry. Link to comment Share on other sites More sharing options...
OldMike Posted October 18, 2010 Author Share Posted October 18, 2010 Thanks; I feel like I'm making progress. I added the following in the setup: Local $ABBYY_Active[$Last_AB] The script runs, but ever gets past the WinWait statement. Waited for a few minutes, and still not moving on. Link to comment Share on other sites More sharing options...
Realm Posted October 18, 2010 Share Posted October 18, 2010 (edited) Thanks; I feel like I'm making progress. I added the following in the setup: Local $ABBYY_Active[$Last_AB] The script runs, but ever gets past the WinWait statement. Waited for a few minutes, and still not moving on. Did you notice that I modified that part to WinActivate, since it's no longer waiting for a window to appear, now you need to activate the window needed. Edit: The last example I Posted works perfectly on my end, which I just noticed that I commented out the part that checks the size of your PDFs, I did that for my tests, you might want to uncomment that out! Edited October 18, 2010 by Realm My Contributions: Unix Timestamp: Calculate Unix time, or seconds since Epoch, accounting for your local timezone and daylight savings time. RegEdit Jumper: A Small & Simple interface based on Yashied's Reg Jumper Function, for searching Hives in your registry. Link to comment Share on other sites More sharing options...
OldMike Posted October 18, 2010 Author Share Posted October 18, 2010 I have a theory on why it does not move on. When ABBYY launches it immediately pops up a window asking if I want to save the previous batch. Answering 'no' is what the Send("n") statement if for. But perhaps this window comes up so fast that the main window cannot report being active fast enough and focus moves on to the pop up, so WinWait is waiting for a report from the main window, but it is not being summoned. So I'll try removing the test for launch, keep it for shutting down later on. Link to comment Share on other sites More sharing options...
Realm Posted October 18, 2010 Share Posted October 18, 2010 Answering 'no' is what the Send("n") statement if for. My bad, I thought it was just a typo and you wanted a new doc to create first. in my last example, take out the '^' CTRL in the send! maybe that will help, if not, you can work the window creation process like this: [size=2]For $a=1 To 4[/size] Run("C:\Program Files\ABBYY FineReader 10\FineReader.exe","",@SW_MAXIMIZE,"") WinWait("ABBYY FineReader 10") Do $text = WinGetText("ABBYY FineReader 10",'') Until StringInStr($text,"no") Send('n') [size=2]Next[/size] My Contributions: Unix Timestamp: Calculate Unix time, or seconds since Epoch, accounting for your local timezone and daylight savings time. RegEdit Jumper: A Small & Simple interface based on Yashied's Reg Jumper Function, for searching Hives in your registry. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now