mwpeck Posted December 27, 2008 Share Posted December 27, 2008 Is it possible to use ControlSend, or some other method, to send keystrokes to a specific process? I need to be able to send the key(s) without focusing on the window, and its possible to have multiple windows with the same name open so I cannot use normal ControlSend as I cannot control if it is sent to the first or second window. I would like to be able to send it to a specific process so I can specify (via identifying the proper process) which window to send the keys to. Link to comment Share on other sites More sharing options...
TurionAltec Posted December 27, 2008 Share Posted December 27, 2008 You could probably use Winlist to get a list of Windows that match the specific title, and then check against the owning process using WinGetProcess Link to comment Share on other sites More sharing options...
TurionAltec Posted December 27, 2008 Share Posted December 27, 2008 This sample program will open 4 copies of notepad, then ask the user for the desired PID to look for. You can use task manager or process explorer to get the desired PID run("notepad.exe","",@SW_MINIMIZE) run("notepad.exe","",@SW_MINIMIZE) run("notepad.exe","",@SW_MINIMIZE) run("notepad.exe","",@SW_MINIMIZE) $winhandle=0 $process= InputBox("Process","Enter the PID of the desired notepad to enter text in") $Windowlist=WinList("Untitled") For $i = 1 to $Windowlist[0][0] If WinGetProcess($Windowlist[$i][1])= $process Then $winhandle=$Windowlist[$i][1] EndIf Next msgbox(0,"Window handle for "& $process, $winhandle) ControlSend($winhandle,"","Edit1","This window handle is " & $winhandle) Link to comment Share on other sites More sharing options...
mwpeck Posted December 27, 2008 Author Share Posted December 27, 2008 Just got back and wow thanks!.....pretty much exactly what I was looking for. I'll probably do a listbox type thing where it shows all the running processes found that match that name, then when the user selects one of them it will activate the window that matches that process ID that way the person knows which one is which without having to check task manager. Any links to GUI tutorial sections? I've never done GUI in autoit so I dont know where to start with that. Link to comment Share on other sites More sharing options...
Andreik Posted December 27, 2008 Share Posted December 27, 2008 Just got back and wow thanks!.....pretty much exactly what I was looking for.I'll probably do a listbox type thing where it shows all the running processes found that match that name, then when the user selects one of them it will activate the window that matches that process ID that way the person knows which one is which without having to check task manager.Any links to GUI tutorial sections? I've never done GUI in autoit so I dont know where to start with that. Here you'll find a lot of help. http://www.autoitscript.com/forum/index.ph...st&p=609033 When the words fail... music speaks. Link to comment Share on other sites More sharing options...
mwpeck Posted December 27, 2008 Author Share Posted December 27, 2008 (edited) Here you'll find a lot of help. http://www.autoitscript.com/forum/index.ph...st&p=609033Thanks a lot, found out about Koda and decided to use that for the design. How can I get the window handle from a process ID? For example, I have: $Windowlist = WinList("Untitled") For $i = 1 to $Windowlist[0][0] GuiCtrlSetData($ProcessList, WinGetProcess($Windowlist[$i][1]) & " - " & $WindowList[$i][0]) Next Func IdentifyProcess() $winhandle = GUICtrlRead($ProcessList) WinActivate($winhandle) EndFunc The problem is, because how I am showing the processes in the listbox, the GUICtrlRead($ProcessList) (when an item is selected) contains PID - Window Name. I am ok with cutting it down the listbox to just contain the PID, but how do I get a window handle from a PID, so I am able to use the IdentiyProcess function (basically it will simply activate the window, so they know the right window is selected in the process list). Edited December 27, 2008 by mwpeck Link to comment Share on other sites More sharing options...
TurionAltec Posted December 27, 2008 Share Posted December 27, 2008 (edited) Depending on what you want you could say "Switch to the desired window and press CTRL+ALT+something", and in the called HotKeySet, use Wingethandle("[ACTIVE]") to get the handle of the desired window. If you want to build a GUI, the Koda GUI builder is your friend. Then just start playing with GUICtrlxxx functions Here's a sample: #include <GUIConstants.au3> #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("Form1", 194, 195, 193, 115) $List1 = GUICtrlCreateList("", 48, 8, 89, 123) $Button1 = GUICtrlCreateButton("Goto", 8, 152, 57, 25, 0) $Button2 = GUICtrlCreateButton("Select", 72, 152, 49, 25, 0) $Windowlist=WinList("Untitled") $whndlist="" For $i = 1 to $Windowlist[0][0] $whndlist=$whndlist& $i & "|" Next GUICtrlSetData($List1,$whndlist) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### While 1 $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $List1 $winhandle=$Windowlist[number(GUICtrlRead($List1))][1] Case $Button1 WinActivate($winhandle) Case $Button2 ControlSend($winhandle,"","Edit1"," This window handle is " & $winhandle) EndSwitch WEnd In this case we only deal with Windows handles, and there's no need to worry about the PID Edited December 27, 2008 by TurionAltec Link to comment Share on other sites More sharing options...
goldenix Posted December 27, 2008 Share Posted December 27, 2008 (edited) Run("notepad.exe") $handle = WinGetHandle('Untitled - Notepad', "") $pid = WinGetProcess($handle) ConsoleWrite($handle & @CRLF) ConsoleWrite($pid & @CRLF) Edited December 27, 2008 by goldenix My Projects:[list][*]Guide - ytube step by step tut for reading memory with autoitscript + samples[*]WinHide - tool to show hide windows, Skinned With GDI+[*]Virtualdub batch job list maker - Batch Process all files with same settings[*]Exp calc - Exp calculator for online games[*]Automated Microsoft SQL Server 2000 installer[*]Image sorter helper for IrfanView - 1 click opens img & move ur mouse to close opened img[/list] Link to comment Share on other sites More sharing options...
TinyBoy Posted December 27, 2008 Share Posted December 27, 2008 Is it possible to use ControlSend, or some other method, to send keystrokes to a specific process? I need to be able to send the key(s) without focusing on the window, and its possible to have multiple windows with the same name open so I cannot use normal ControlSend as I cannot control if it is sent to the first or second window. I would like to be able to send it to a specific process so I can specify (via identifying the proper process) which window to send the keys to.I use this function for such a case: Copied it from a sample topic, but can't find it again. CODE#include <array.au3> $iPid = Run("notepad.exe") Sleep(100) ; allow notepad to create window $aArray = _WinGetInfoByProcess($iPid, 1) _ArrayDisplay($aArray, "by Pid, only visible windows") $aArray = _WinGetInfoByProcess("notepad.exe", -1) _ArrayDisplay($aArray, "by Name, all windows") $aArray = _WinGetInfoByProcess("notepad.exe", 0) _ArrayDisplay($aArray, "by Name, only invisible windows") $aArray = _WinGetInfoByProcess("notepad.exe", 1) _ArrayDisplay($aArray, "by Name, only visible windows") $hHandle = _WinGetInfoByProcess("notepad.exe") ; default is $nShow = 2 ControlSend($hHandle, "", "", "{alt}{right 2}{down 2}{enter}") Sleep(300 * ControlSend("[active]", "", "", "{tab 2}{BS}72{enter}")) ; allow window to change ControlSend("[active]", "", "", "{enter} Hello World.") Func _WinGetInfoByProcess($vProcess, $nShow = 2) ; ;=============================================================================== ; ; Function Name: _WinGetInfoByProcess ; Description:: Get Window Handle of Process ; Parameter(s): $vProcess = Processname(e.g. "Notepad.exe") or Processnumber(e.g. 4711 ) ; $nShow = -1 "All (Visble or not)" ; $nShow = 0 "Not Visible Only" ; $nShow = 1 "Visible Only" ; $nShow = 2 "Return handle of newest window " (Default) ; Requirement(s): none ; Return Value(s): ; @extended = returns number of entries in the array ; @error = 0 AND $nShow = 2 (default) returns handle of newest window ; @error = 0 returns array with processinfos ; n = 1 to @extended ; Array[n][0] shows windows title. ; Array[n][1] shows windows handle. ; Array[n][2] shows windows Pid. ; @error = 1 Process not found. ; @error = 2 Window not found. ; Author(s): Hubertus ; inspired by Smoke_N's script _WinGetHandleByPID() ; but to handle more than one process with the same name ; and to return handle of newest window ($nShow = 2). ; tested versions: Autoit 3.2.12.1 and Beta 3.2.13.10 ; ;=============================================================================== ; If Not ProcessExists($vProcess) Then Return SetError(1, 0, 0) ; no matching process Local $iWinList, $aWinList = WinList() Local $iResult, $aResult[uBound($aWinList)][3] Local $iProcessList, $aProcessList = ProcessList($vProcess) If $aProcessList[0][0] = 0 Then Local $aProcessList[2][2] = [[1, 0],["", $vProcess]] For $iWinList = 1 To $aWinList[0][0] For $iProcessList = 1 To $aProcessList[0][0] If WinGetProcess($aWinList[$iWinList][1]) = $aProcessList[$iProcessList][1] Then If $nShow > -1 And Not $nShow = (2 = BitAND(WinGetState($aWinList[$iWinList][1]), 2)) Then ContinueLoop $iResult += 1 $aResult[$iResult][0] = $aWinList[$iWinList][0] $aResult[$iResult][1] = $aWinList[$iWinList][1] $aResult[$iResult][2] = $aProcessList[$iProcessList][1] EndIf Next Next If $iResult = 0 Then Return SetError(2, 0, 0) ; no window found ReDim $aResult[$iResult + 1][3] $aResult[0][0] = $iResult If $nShow = 2 Then Return SetError(0, $iResult, $aResult[1][1]) Return SetError(0, $iResult, $aResult) EndFunc ;==>_WinGetInfoByProcess Link to comment Share on other sites More sharing options...
TurionAltec Posted December 27, 2008 Share Posted December 27, 2008 How can I get the window handle from a process ID?The problem is, because how I am showing the processes in the listbox, the GUICtrlRead($ProcessList) (when an item is selected) contains PID - Window Name.I am ok with cutting it down the listbox to just contain the PID, but how do I get a window handle from a PID, so I am able to use the IdentiyProcess function (basically it will simply activate the window, so they know the right window is selected in the process list).You can either do a loop with Winlist and WinGetProcessor have a look at BrettF's code in this thread:http://www.autoitscript.com/forum/index.ph...handle+from+pid Link to comment Share on other sites More sharing options...
Ronan Posted May 26, 2009 Share Posted May 26, 2009 Hi there, i came across this forum, modified the examples given, but i encounter another problem. I tried to make the ControlSend function to sent to multiple windows but failed. Here is my codes CODE$Windowlist=WinList("Example") If WinExists ($Windowlist[1][1]) Then $Windowhandle1 = $Windowlist[1][1] EndIf If WinExists ($Windowlist[2][1]) Then $Windowhandle2 = $Windowlist[2][1] EndIf If WinExists (HWnd($Windowhandle1)) Then Call("Gameloop1") EndIf If WinExists (HWnd($Windowhandle2)) Then Call("Gameloop2") EndIf Func Gameloop1() ControlSend (HWnd($Windowhandle1), "", "", "{F1}") Sleep(3000) ; Call("Gameloop1") EndFunc Func Gameloop2() ControlSend (HWnd($Windowhandle2), "", "", "{F1}") Sleep(3000) Call("Gameloop2") EndFunc And my problem is..if i have 2 of that similar windows opened, it send to the 1st window but not the 2nd window. And if i have only 1 window opened, the error message saying something like If WinExists ($Windowlist[2][0]) Then If WinExists (^ERROR Error: Array variable has incorrect number of subscripts or subscript dimension range exceeded. Hmm..so what's wrong with my codes?? Help me please...!! Link to comment Share on other sites More sharing options...
oMBRa Posted May 26, 2009 Share Posted May 26, 2009 u are trying to access to an element of the array that doesnt exist ( because the array is too small ) basically u have to check $Windowlist[0][0] to know how many windows are found, then act properly. with this: If WinExists ($Windowlist[2][1]) Then u are saying that ''WinList'' found 2 windows but, as a matter of fact it found only 1 ( that's why pops up that error ). another thing: HWnd($Windowhandle1)) it's wrong because $Windowhandle1 it's already an Handle. Link to comment Share on other sites More sharing options...
Ronan Posted May 26, 2009 Share Posted May 26, 2009 (edited) Hmm...but then when i do like this below it returns "the list is 2" CODE $Windowlist=WinList("Example") $which=$Windowlist[0][0] If WinExists (HWnd($which)) Then msgbox(4096,"List","the list is "& $which) And when i type like this it works well too. CODEIf WinExists ($Windowlist[1][0]) Then $Windowlhandle1 = $Windowlist[1][1] EndIf If WinExists (HWnd($Windowlhandle1)) Then Call("Gameloop1") EndIf Func Gameloop1() ControlSend (HWnd($Windowlhandle1), "", "", "{F1}") Sleep(3000) Call("Gameloop1") EndFunc The problem only appears when the 2nd one comes in. Edited May 26, 2009 by Ronan 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