Sign in to follow this  
Followers 0
mwpeck

ControlSend (or any other way) to send keys to a process?

13 posts in this topic

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.

Share this post


Link to post
Share on other sites



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

Share this post


Link to post
Share on other sites

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)

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Here you'll find a lot of help. :)

http://www.autoitscript.com/forum/index.ph...st&p=609033


When the words fail... music speaks

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

Thanks 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 by mwpeck

Share this post


Link to post
Share on other sites

#7 ·  Posted (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 by TurionAltec

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Run("notepad.exe")
$handle = WinGetHandle('Untitled - Notepad', "")
$pid = WinGetProcess($handle)

ConsoleWrite($handle & @CRLF)
ConsoleWrite($pid & @CRLF)

Edited 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]

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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 WinGetProcess

or have a look at BrettF's code in this thread:

http://www.autoitscript.com/forum/index.ph...handle+from+pid

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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.

Share this post


Link to post
Share on other sites

#13 ·  Posted (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.

CODE
If 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 by Ronan

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
Sign in to follow this  
Followers 0