Crivens

ControlSend issue

14 posts in this topic

Hello. Got an issue hopefully someone maybe able to help with.

I need to keep alive several windows, which if inactive for more than X minutes will die off. I have a script that auto starts several of these windows, as well as other things like positioning them around my desktops. The important point is that the windows are all the same program (eg. like multiple Notepads open), and have their own title (eg. "Bob1", "Bob2", "Bob3" etc).

Ok, so I have a script I wrote that checks the Windows exist using Winactivate, and then I send {ENTER} to make sure it stays awake. This all works really well, if I go for a coffee break or whatever. 

However some of these windows will stay inactive, as they are rarely used even when I'm using the PC. The issue comes in that these rarely used windows will die off as I'm using the PC, and the keep alive script is annoying, because if I'm using another application (eg. Chrome), then these windows will popup and become active. Annoying if you are trying to do something else, and really annoying if your current key presses go to the background windows rather than the current application. 

So, I looked into replacing WinActivate and Send with ControlSend. Should be perfect as it looks like it works in the background.

Unfortunately, for some reason ControlSend only sends the text to the last active window from my list of background windows. I've checked the handles using the same title as I use for the ControlSend command, and it all looks good to me, so not sure what is wrong, or if there is an issue with AutoIT.

Any ideas?

Cheers

Share this post


Link to post
Share on other sites



  1. No Notepad didn't autoclose windows.
  2. ControlSend can work with most hidden windows
  3. some pc-games are very resistant against automation.

=> try allone, or show your script code.

Share this post


Link to post
Share on other sites

Good point. Here is the current script:-

#include <Date.au3>
dim $FSATemp,$tOut=60,$sTime=_NowCalc(),$sTimeDisplay=_NowTime(),$text,$tDiff,$debug
Opt("WinTitleMatchMode", 3) ;Match exactly same title. Otherwise IBM1 can find IBM11
while 1
   For $fsaloop=1 to 99
      $FSATemp="IBM" & string($fsaloop)
      if winactivate($FSATemp)<>0 then send("{ENTER}")
      ;$handle=WinGetHandle($FSATemp)
      ;ControlSend($handle,"","","bob")
   Next
   $tDiff=_DateDiff('n',$sTime,_NowCalc())
   if $tDiff=0 then
      $tDiff=_DateDiff('s',$sTime,_NowCalc())
      $text=Number($tDiff)&" second"
   Else
      $text=Number($tDiff)&" minute"
   EndIf
   if $tDiff<>1 then $text=$text&"s"
   $ask=msgbox(1,"FSA Auto Keep Alive","Only use if away from PC, to keep FSA sessions alive. OK to Run, Cancel to Exit."&@LF&@LF&"Auto refreshes every "&$tOut&" seconds."&@LF&@LF&"Started at "&$sTimeDisplay&". Running for "&$text&".",$tOut)
   if $ask=2 then ExitLoop
   WEnd
   ;msgbox(4096,"Debug",$debug)
Exit

This works, but activates the windows, which I don't want. If I remove the winactivate line, and instead use the ControlSend line (with the handle line, or without and only using title like I do with winactivate results in the same effect), then it only sends the "bob" text to the last instance of "IBM" titled windows of my application (multiple running instances), instead of all of them. They are titled "IBM1", "IBM2" etc.

If it helps I can post the creation script.

Cheers

Share this post


Link to post
Share on other sites

Do you have to "keepalive" specific IBM windows at specific times? or can you just "keepalive" all instances of IBM window with every pass?

your last paragraph confused me but if you are saying Controlsend to wintitle works without activating window and interrupting then you should be able to loop through each IBM window until finished. change the wintitlematchmode to partial or beginning instead of exact.


if @error Then
	MsgBox(262192,"",@ComputerName&" slaps "&@UserName&" around a bit with a large trout!")
	EndIf

>Exit code: 0

REAL search results

"Yeah yeah yeah, patience. How long will that take?"  -Ed Gruberman

Share this post


Link to post
Share on other sites

It doesn't have to be at specific times, it just runs every minute as I don't really need to wake the application up more than that really. Once every 10 minutes would probably be fine to be honest.

It loops through each window fine, but when I use Controlsend instead of WinActivate and Send, then it only sends the text to the last window that was used. So I click on one of the "IBM" windows, and then run the keepalive script, and the text only gets sent to that last "IBM" window that I clicked on. The window itself doesn't get activated, so that is something, but using WinActivate and Send (as seen in script above) activates each "IBM" window correctly, and sends text to each one.

The wintitlematchmode is set to exact, because otherwise I found that it can pick up the wrong window. If I have "IBM1" and "IBM11" for example, then trying to select the "IBM1" window can get me the "IBM11" window.

Share this post


Link to post
Share on other sites

It looks like something simple should work, i cant test because i am not in your desktop environment.

maybe this...

Opt("WinTitleMatchMode", 3)

 For $n=1 to 99
      $win="IBM" & $n
      $handle=WinGetHandle($win)
      ControlSend($handle,"","","bob")
      Next

 


if @error Then
	MsgBox(262192,"",@ComputerName&" slaps "&@UserName&" around a bit with a large trout!")
	EndIf

>Exit code: 0

REAL search results

"Yeah yeah yeah, patience. How long will that take?"  -Ed Gruberman

Share this post


Link to post
Share on other sites

That's exactly what I do already in my commented code. If you comment out the winactivate line, and uncomment the wingethandle and controlsend lines, then I'm doing exactly the same thing. This is what causes the issue. The code at the minute works completely correctly (but activates all the windows) with the winactivate and send commands. Note that I have the same issues by using the title in ControlSend rather than using the obtained handle (which we have both done in our scripts).

It's like it can find all the window handles without issue for many occurrences of the same program (but with different titles), but for some reason ControlSend either only works on the last used window of the program, or oddly the handle is translated into the same window every time.

Cheers

Share this post


Link to post
Share on other sites

do you have a control number for the IBM windows? using the AutoIt window info tool should give a control id of some sorts.

doing this with 6 notepads open named "win1.txt" thru "win6.txt" with a control id of 15 which is the same for each window worked without bringing the windows to the front. i took out the exact wintitlematchmode

For $n=1 to 6
      $win="win" & $n & ".txt"
      $handle=WinGetHandle($win)
      ControlSend($handle,"",15,"bob")
      Next

script took a second to complete and each window had "bob" written to it, and none were activated or blocked my work.


if @error Then
	MsgBox(262192,"",@ComputerName&" slaps "&@UserName&" around a bit with a large trout!")
	EndIf

>Exit code: 0

REAL search results

"Yeah yeah yeah, patience. How long will that take?"  -Ed Gruberman

Share this post


Link to post
Share on other sites

That's what I'm talking about. Nice one! 10 years almost since I last used AutoIT, and problem solved within a few hours. Impressive :)

Just to sum up; yes it did have a control number (control ID in AutoIT windows info tool). I didn't change anything else except the ControlSend line to use the control ID of my application, and bingo it all looks like it works fine.

Awesome stuff. Thanks Alienclone!

Share this post


Link to post
Share on other sites
Just now, JohnOne said:

You might also consider using WinList and Ubound instead of just looping to 99.

well that takes the fun out of my "heavy handed" attempt at tasking my CPU.

I just yell commands at my pc all day, if my program is open, it runs the command, if not open then, nothing. no harm no foul.


if @error Then
	MsgBox(262192,"",@ComputerName&" slaps "&@UserName&" around a bit with a large trout!")
	EndIf

>Exit code: 0

REAL search results

"Yeah yeah yeah, patience. How long will that take?"  -Ed Gruberman

Share this post


Link to post
Share on other sites

I know, but it's a simple script to get no more than like 12 windows up and running over 3 screens. Nothing complicated. It doesn't even go to the customer, just for me in one specific development environment. 

Cheers

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

Controlsend is as unreliable as send, just to a lesser degree.  ControlSetText works without the window being active.  You can then make the windows hidden, and not be bothered by the script.

Edited by jdelaney

IEbyXPATH-Grab IE DOM objects by XPATH IEscriptRecord-Makings of an IE script recorder ExcelFromXML-Create Excel docs without excel installed GetAllWindowControls-Output all control data on a given window.

Share this post


Link to post
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