AutoHotKey - Run a program once send several times - autohotkey

I am pretty new to AutoHotkey, but I managed it to start my desired program and send an Enter-Key to it, but the probleme here is, the program should only start once and if started it should only receive that enter key, when I press the key stroke again and again it should only send that enter key.
And the program should should stay in the background and not focus after it receives the enter key.
My Code:
#n::
Run F:\V..c.exe
Send {enter}
return

Detect if the process exists and start the program minimized, then wait for its window to appear.
#n::
process, exist, PROGRAM.EXE
if (errorlevel = 0) {
run, d:\program.exe, , min
winwait, ahk_class PROGRAM_WINDOW_CLASS
}
controlSend, , {Enter}, ahk_class PROGRAM_WINDOW_CLASS
;or use the line below
;controlSend, ahk_parent, {Enter}, ahk_class PROGRAM_WINDOW_CLASS
return
Replace PROGRAM.EXE with the executable name of your program and PROGRAM_WINDOW_CLASS with the window class as seen in the Autohotkey Window Spy utility available in Start menu or in the folder of the Autohotkey (AU3_Spy.exe) or in the right click menu of the Autohotkey tray icon.
Instead of running the program minimized it's also possible to use SW_SHOWNOACTIVATE flag of shellExecute, so you can replace the run, d:\program,, min with this:
dllCall("shell32\ShellExecute", uint,0, uint,0, str,"d:\program.exe", uint,0, uint,0
,uint,SW_SHOWNOACTIVATE:=4)

you could try:
hasran := false
#n::
if (!hasran) {
Run F:\V..c.exe
hasran := true
}
Send {enter}
return
It wont check if that windows exists, but it will only run the program once. then you can navigate to that program and it will only hit the enter key. (if that program is not gui I dont think you can send key events to it)

Related

autohotkey how to activate last opened window that changes its pid

I'm trying to setup a hotkey to always launch a new WindowsTerminal window and give it focus. Even if there is an existing window, I always want it to create a new window. I'm able to get the new window to run, but I'm having difficulty making it the Active window.
Capturing the pid during the Run command and using ahk_pid doesn't seem to work as the pid changes between launch and the active window that appears (msgbox debugging shows one pid, Window Spy shows a different pid). Using WinWait, ahk_exe WindowsTerminal.exe seems to return right away grabbing a pre-existing window.
#t::
Run, wt.exe, , , TermPid
;; TermPid seems to change between the launch and the final window that appears
WinWait, ahk_pid %TermPid%, , 3
if ErrorLevel {
MsgBox, WinWait timed out... %TermPid%
return
} else {
WinActivate
}
;; problems when there are other already existing WindowsTerminal.exe windows
;WinWait, ahk_exe WindowsTerminal.exe, , 3
;if ErrorLevel {
; MsgBox, WinWait timed out...
; return
;} else {
; WinActivate
;}
return
I tried to create before and after array containing the PIDs to determine which process was the newly created one, but targeting the last PID in the array created below seems to work as is.
Code:
#t::
Run, wt.exe
;If you are on a slow computer, you may need to increase this delay
Sleep 100 ;Forgot how to optimize this w/ WinWait, but not important rn bc its not critical
newArray:=[]
for proc in ComObjGet("winmgmts:").ExecQuery("Select * from Win32_Process"){
if(proc.Name=="WindowsTerminal.exe"){
prID := proc.ProcessId
newArray.Push(prID)
}
}
LastItem:=newArray[newArray.MaxIndex()]
WinActivate, ahk_pid %LastItem%
return

Use AutoHotkey to launch a game in an emulator

I want to create an .ahk script, that launches a game with an emulator. When the emulator is opened, it should send F10 to load a save state to get me directly to the game menu and jump the intros. This is what i got so far:
Run, C:\Users\****\Documents\!Others\Emulators\SNES9x\snes9x-x64.exe -fullscreen "E:\Consoles\Nintendo SNES\Goof Troop\Goof Troop.smc"
Sleep, 100
IfWinExist ahk_class Snes9X: WndClass
{
WinActivate
WinWaitActive
IfWinActive ahk_class Snes9X: WndClass
Send, {F10}
Return
}
I want to make sure that F10 is sent in the right time. The script should wait for the emulator to open first, am I doing it right?
Another thing that i have no idea on how to do, is to convert Xinput to Keyboard, for example when I am in-game and press LB + RB + B it converts it to ALT+F4 and closes the window, how can I do this?
The way i do is, suppose if the name of the emulator process is snes9x-x64.exe, then
processName := "snes9x-x64.exe"
run %processName%
flag = 0
Loop
{
WinGetTitle, title, ahk_exe %processName%
IfWinActive, %title%
{
If flag = 0
{
Send, {F10}
flag = 1
}
}
}
here once the emulator is opened we will check whether the window is active in a loop and then send F10 and stop the loop once the window is active using a flag.
And for the LB + RB + B, you will have to use a keyboard simulator like xpadder and map the keys LB,RB and B to keyboard keys and define a shortcut for that.

How do I update the auto hot keys config once saved from a script?

I have a shortcut to open the current running script in a text editor and then save it and close it. Upon closing, how do I update ahk to use the new updated settings?
This is what I have:
IfWinExist, test.ahk ahk_exe notepad.exe
{
WinActivate
Sleep, 100
Send, ^s
Sleep, 200
WinClose
}
else
MsgBox, window not found
app1Open=false
Reload
If you want to restart the script itself (that is, from its own process), use the Reload command.
Otherwise, if you want to restart the script from another process, you have to close it and then run the script again. In this case, you can either kill the script's process and run it again (not nice!). Or you can tell the script to gracefully Reload, for example in one of these two ways:
Inter-process communication: OnMessage() for the receiving process and PostMessage/SendMessage in the sending process
Defining a simple hotkey in your receiving script and sending that hotkey from another process
As MCL mentioned, use Reload. There is no need to close the script. Here is an example:
^!#r:: ; Save and Reload the script with Alt+Ctrl+Win+r
IfWinExist, SciTE4AutoHotKey
{
WinActivate
Sleep, 100
Send, ^s
Sleep, 300
}
Reload
Return

Auto Maximize skype live conversation window with Autohotkey

Here is what I'm trying to do and would greatly appreciate any help here.
I am trying to automate maximizing the live conversation window in skype with an Autohotkey script. I'm trying to make it so I can call into a remote machine using skype and have it auto answer (this is native in skype)...once I have a live conversation window I would like to maximize the live conversation window to fill the screen.
I've given this a shot but somehow don't think that I have the correct ahk_class for the live conversation window but there may be something else I am missing. I've placed a the code I've tried using below...any help would be great.
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn ; Enable warnings to assist with detecting common errors.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#Persistent
IfWinExist, TLiveConversationWindow ;
{
WinActivate
WinMaximize
send !{Enter};When using skype normally this Alt+Enter will maximize the window
return
}
I also tried to use this code to determine the proper class for the live conversation window...but has not helped as of yet.
Alt & Enter::
IfWinExist, TLiveConversationWindow
WinActivate
ControlFocus, ClassNN TLiveConversation1
ControlClick, ClassNN TLiveConversation1, , , , 2,
MouseClick, left, , , 2
send !{Enter}
; now we get the ID & CLASS
WinGet, Active_Window_ID, ID, A
WinGetClass, Active_Window_Class, A
MsgBox, The active window's class is "%Active_Window_class%" and ID is %Active_Window_ID%
Was able to get a simplified version of the code to work with a hotkey to initiate but have not been able to get the WinWait function to work as per #Schneyer.
Functioning Code activated by hotkey
#NoEnv
#Warn
#Persistent
SendMode Input
SetWorkingDir %A_ScriptDir%
; Skype Maximizer initiating functions
^!p::
;WinWait ahk_class TLiveConversation1
;WinWait ahk_class TConversationForm
;WinWait ahk_class TLiveConversationWindow
;WinMaximize ahk_class TLiveConversation1
;functioning code
;Activate tSkMainForm.
WinActivate ahk_class tSkMainForm
;Send Alt Enter Input to maximize.
SendInput !{Enter}
;TLiveConversationWindow Always On Top
WinSet, AlwaysOnTop,,ahk_class TLiveConversationWindow
;Minimize main form
WinMinimize ahk_class tSkMainForm
Return
When swapping the ^!p:: with any of the WinWait Functions nothing seems to happen. The WinWait seems like it should be the proper method, any thoughts on why it won't work?
Problems
#persistent lets the script run, but your code still gets executed only once when you start the script. After that it stays active but does nothing.
Use a WinWait to wait for the window to appear (wrap it in a Loop if you want it to run more than once).
Use ahk_class to to search for a window class instead of the window title
Working code
You can use the Window Spy tool which is included in AHK. Use the tray icon menu of a running AHK script to start it.
I use TConversationForm in the code, but it works with every window class.
#NoEnv
#Warn
SendMode Input
SetWorkingDir %A_ScriptDir%
WinWait ahk_class TConversationForm
WinActivate
WinMaximize
Scanning through AHK forums I was able to find a post that led me to the answer for this little problem. Check the below link for further information.
https://autohotkey.com/board/topic/96491-detect-when-a-classnn-window-exists/
The problem with using ahk_class to identify when a skype call was active is that the "active call window" identified as classNN TLiveConversation1 in the inspector was actually a Control within the window of ahk_class tSkMainForm rather than a Window. This made the WinWait function ineffective at identifying it when the call initiated.
In order to identify the Control it is necessary to loop through the controls (using WinGet) in ahk_class tSkMainForm until the TLiveConversation exists and then kick off any subroutines needed. For me that was to maximize the live conversation window.
You'll see the code to do this starting with the WinGet function. All of this is wrapped in a while loop so that it will run persistently allowing it to be called over and over. In essence this code will do the following:
Create a list (SkypeControlList) of controls existing in ahk_class tSkMainForm.
Continually Loop Through SkypeControlList
When a new Live Conversation is initiated a control TLiveConversation1 will exist
Once TLiveConversation1 esists run necessary code
#NoEnv
#Warn
#Persistent
SendMode Event
SetWorkingDir %A_ScriptDir%
DetectHiddenWindows, on
stop = 0
Loop
{
While stop = 0
{
WinGet, SkypeControlList, ControlList, ahk_class tSkMainForm
Loop, Parse,SkypeControlList, `n
{
;Loop to search for control TLiveConversation1
if (A_LoopField = "TLiveConversation1")
{
;Deactivate active screensaver
PostMessage, 0x0112, 0x0F060, 0,, A
;RegWrite REG_SZ, HKEY_CURRENT_USER, Control Panel\Desktop, ScreenSaveActive, 0
;SetKeyDelay, 500
Send {Esc}
;Activate tSkMainForm.
WinActivate ahk_class tSkMainForm
;Send Alt Enter Input to maximize.
Send !{Enter}
;TLiveConversationWindow Always On Top
WinSet, AlwaysOnTop,,ahk_class TLiveConversationWindow
stop = 1
sleep, 100
}
}
}
IfWinExist ahk_class TLiveConversationWindow
{
stop = 1
sleep, 1000
}
IfWinNotExist ahk_class TLiveConversationWindow
{
;Minimize all windows by win+D show desktop
send #d
sleep,1000
; is that call quality feedback window up? kill it.
SetTitleMatchMode, Regex
WinClose, ^Skype.*Call quality feedback$
stop = 0
}
sleep 1000
}
Return
The above code works great as long as there is no screen saver active on the machine being called. If there is an active screen saver the call will answer but the screen saver will not go away. You can see remnants of code trying to wake the computer from a screen saver (This does not currently work).
I've also added a few bits of code to clean up the experience such as removing the call quality popup window that skype throws up after a call as well as clearing the desktop after the call ends.
Thanks to #Blauhirn and #Schneyer for their input in trying to get this solved.

How can I make the script run automatically, without a hotkey being defined?

I want to create a "PolyEdit" script.
Below is the script.
!M::
IfWinActive, ahk_class TMainForm
{
sleep 2000
Send Now is the time
Return
}
The purpose of the script is to:
Send keystrokes and mouse clicks to my default program for opening text files.
That default program is called "PolyEdit".
But I need the script to run without a hotkey being defined.
Right now, in it's present form, with a hotkey defined, it runs just fine.
My question is:
How can I make the script run automatically, without a hotkey being defined?
As Armin already wrote, use #Persistent. Also, If you want to create hotkeys that are only active when a specific application is in focus you can do the following: In this case the script will no longer execute on startup, only when you press the hotkey though...
#Persistent
#SingleInstance
#IfWinActive, ahk_class TMainForm
!M::
sleep 2000
Send Now is the time
Return
!n::SoundBeep, 500, 500
!o::MsgBox, OK
#IfWinActive
This way all 3 (dummy) hotkeys will only be active when your application is in focus! You can define the same hotkeys for another application, just repeat the code but use the ID if the other application in the #IfWinActive, ahk_class TMainForm line.
If you want to send a message every 2 seconds when your application is active do the following:
#Persistent
#SingleInstance
SetTimerMatchMode, CheckApp, 2000
Return
CheckApp:
IfWinActive, ahk_class TMainForm
{
Send, Now is the time
}
Return
If you want to execute a script every time you (re)activate (put in focus) your application (so not every two seconds) then use the following:
#Persistent
#installKeybdHook
#SingleInstance
Gui +LastFound
hWnd := WinExist()
DllCall( "RegisterShellHookWindow", UInt,Hwnd )
MsgNum := DllCall( "RegisterWindowMessage", Str,"SHELLHOOK" )
OnMessage( MsgNum, "ShellMessage" )
Return
ShellMessage( wParam )
{
If (wParam = 4)
{
IfWinActive ahk_class TMainForm
{
Send, Now is the time
}
}
}
Return
Take a look at #Persistent which will keep script running.
If this directive is present anywhere in the script, that script will stay running after the auto-execute section (top part of the script) completes