Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

Execute AHK code dynamically!


  • Please log in to reply
54 replies to this topic
jonny
  • Members
  • 2951 posts
  • Last active: Feb 24 2008 04:22 AM
  • Joined: 13 Nov 2004
New version! All parameters except the command are now optional. The limitation on WinMenuSelectItem has also been removed.

This is a function made for the sole intention of executing other AHK commands. It is currently capable of running almost every AHK command which is practical to run dynamically. See the full list below. The basic idea is that the function will return the OutputVar, if any, or simply execute the given command. If there is more than one OutputVar, they are instead stored in the global array "r". (There are 7 variables in the array) For instance, ControlGetPos would store X in r1, Y in r2, Width in r3, and Height in r4. Also note that ErrorLevel is set globally. When a command has one or more OutputVars, those parameters are not just ignored, they're excluded. That is, the first parameter of the function (other than the "command" parameter) corresponds to the first non-OutputVar parameter in the command. For instance, the first parameter passed when ControlGetPos is the command would correspond to the Control parameter. The FutureUse parameter in InputBox is also skipped over this way.

Also note that due to containing Gui, Hotkey, and other related commands, this function will automatically make a script persistent.

The syntax for this function is:
Execute("Command","Parameter... 1","2","3","4","5","6","7","8","9","10","11")

For example:
execute(mycmd,param1[1] + param1[2],param2)
execute("msgbox","It works!")


Here is a list of commands currently supported. If there is no note beside a command, it conforms with the rules specified above. Also, any commands that use OutputVar will not use the "r" array unless specified here.

AutoTrim
BlockInput
ClipWait
Control
ControlClick
ControlFocus
ControlGet
ControlGetFocus
ControlGetPos: Uses the "r" array.
ControlGetText
ControlMove
ControlSend
ControlSendRaw
ControlSetText
CoordMode
DetectHiddenText
DetectHiddenWindows
Drive
DriveGet
DriveSpaceFree
Edit
EnvAdd
EnvDiv
EnvMult
EnvSet
EnvSub
EnvUpdate
ExitApp
FileAppend
FileCopy
FileCopyDir
FileCreateDir
FileCreateShortcut
FileDelete
FileGetAttrib
FileGetShortcut: Uses the "r" array. (All seven!)
FileGetSize
FileGetTime
FileGetVersion
FileMove
FileMoveDir
FileRead
FileReadLine
FileRecycle
FileRecycleEmpty
FileRemoveDir
FileSelectFile
FileSelectFolder
FileSetAttrib
FileSetTime
GetKeyState
GroupActivate
GroupAdd
GroupClose
GroupDeactivate
Gui
GuiControl
GuiControlGet
Hotkey
IfEqual: Uses a special method of returning; it returns 1 (true) if the If statement was evaluated to true or 0 (false) if it wasn't.
IfNotEqual: See note for IfEqual.
IfExist: See note for IfEqual.
IfNotExist: See note for IfEqual.
IfGreater: See note for IfEqual.
IfGreaterOrEqual: See note for IfEqual.
IfInString: See note for IfEqual.
IfNotInString: See note for IfEqual.
IfLess: See Note for IfEqual.
IfLessOrEqual: See note for IfEqual.
IfMsgBox: See note for IfEqual.
IfWinActive: See note for IfEqual. Also note that the built-in function WinActive() may be an option too.
IfWinNotActive: See note for IfWinActive.
IfWinExist: See note for IfEqual. Also note that the built-in function WinExist() may be an option too.
IfWinNotExist: See note for IfWinExist.
ImageSearch: Uses the "r" array.
IniDelete
IniRead
IniWrite
Input
InputBox: Skips over the FutureUse parameter. (In other words, TimeOut is in the eighth field, not Font)
KeyHistory
KeyWait
ListHotkeys
ListLines
ListVars
Menu
MouseClick
MouseClickDrag
MouseGetPos: Uses the "r" array.
MouseMove
MsgBox: Has special handling for parameters. If only one parameter is detected (non-false, meaning not blank or zero), it will run it that way, so the command can do automatic comma detection. If two or three are detected, it will run it in full-parameter mode, but without parameter four. If all parameters are detected, all parameters will be included in the command.
OnExit
OutputDebug
Pause
PixelGetColor
PixelSearch: Uses the "r" array.
PostMessage
Process
Progress
Random
RegDelete
RegRead: The obsolete 5-param method is not supported.
RegWrite
Reload
Run
RunAs
RunWait
Send
SendRaw
SendMessage: This is currently the only command that will return the value of ErrorLevel (since it would be pointless for it to wait otherwise).
SetBatchLines
SetCapslockState
SetControlDelay
SetDefaultMouseSpeed
SetFormat
SetKeyDelay
SetMouseDelay
SetNumlockState
SetScrollLockState
SetStoreCapslockMode
SetTimer
SetTitleMatchMode
SetWinDelay
SetWorkingDir
Shutdown
Sleep
Sort
SoundBeep
SoundGet
SoundGetWaveVolume
SoundPlay
SoundSet
SoundSetWaveVolume
SplashImage
SplashTextOn
SplashTextOff
SplitPath: Uses the "r" array.
StatusBarGetText
StatusBarWait
StringCaseSense: Note! This will affect the case sensitivity of the primitive syntax checker in this function if on; it will not work unless they are written exactly as they are here, with cameling (StringCaseSense would be allowed through, stringcasesense wouldn't). This also goes for any external use of this command.
StringGetPos
StringLeft
StringLen
StringLower
StringMid
StringReplace
StringRight
StringSplit: The Output* parameter in this one is not like other ones, and it counts as a parameter for the purposes of this function.
StringTrimLeft
StringTrimRight
StringUpper
Suspend: Permit is already set in the function, so this command can be safely used.
SysGet
Thread
ToolTip
Transform
TrayTip
URLDownloadToFile
WinActivate
WinActivateBottom
WinClose
WinGetActiveStats: Uses the "r" array.
WinGetActiveTitle
WinGetClass
WinGet
WinGetPos
WinGetText
WinGetTitle
WinHide
WinKill
WinMaximize
WinMenuSelectItem
WinMinimize
WinMinimizeAll
WinMinimizeAllUndo
WinMove: Supports the 2-param mode.
WinRestore
WinSet
WinSetTitle
WinShow
WinWait
WinWaitActive
WinWaitClose
WinWaitNotActive

Download

Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
Great solution until something gets built-in, which as I said earlier might be a long time. Fortunately, I don't feel nearly as guilty about deferring this feature now that you've come up with this nicely structured function which others can copy & paste or include via #Include.

Thanks.

jonny
  • Members
  • 2951 posts
  • Last active: Feb 24 2008 04:22 AM
  • Joined: 13 Nov 2004
No problem, Chris. It was a lot of fun making this. I haven't given much thought to the multi-line idea yet, but if it's feasible I'll certainly try. If I succeed, a built-in function would be proven virtually unnecessary.

Also, I've adapted my old clunker Cmd.Ahk into a small gui wrapper for the function, just to demonstrate. Execute.ahk has to be in the same folder for it to work.

#include execute.ahk
#singleinstance off
#notrayicon

gui,add,edit,readonly vcmdedit w250 h250
gui,add,edit,vcmdfield
gui,add,button,default hidden gsubmit x10 y10 w1 h1
menu,Menubar,add,&Menu,:TRAY
gui,menu,Menubar
gui,+resize
gui,show,center,AutoHotkey Prompt
return

guisize:
new_w := (A_GuiWidth - 20)
new_h := (A_GuiHeight - 39)
field_y := (A_GuiHeight - 30)
guicontrol,move,cmdedit,w%new_w% h%new_h%
guicontrol,move,cmdfield,w%new_w% y%field_y% x10
return

submit:
gui,submit,nohide
guicontrol,,cmdedit,Working...
stringsplit,param,cmdfield,`,
guicontrol,,cmdedit,% "Output: " . execute(param1,param2,param3,param4,param5,param6,param7,param8,param9,param10) . "`nErrorLevel: " . ErrorLevel . "`n`nOutput Array:`n1: " . r1 . "`n2: " . r2 . "`n3: " . r3 . "`n4: " . r4 . "`n5: " . r5 . "`n6: " . r6 . "`n7: " . r7
guicontrol,,cmdfield,
r1=
r2=
r3=
r4=
r5=
r6=
r7=
return

guiclose:
exitapp

Note: The "guicontrol,,cmdfield," line is supposed to be the line right under the "guicontrol,,cmdedit," line. If your browser renders it differently, make sure you delete the extra linefeeds when you paste it.

jonny
  • Members
  • 2951 posts
  • Last active: Feb 24 2008 04:22 AM
  • Joined: 13 Nov 2004
I've made some improvements, taking advantage of the recent addition of optional function parameters. Thanks Chris!

If anyone has a suggestion or notices a command I missed, feel free to speak up! Criticism is also welcome.

polyethene
  • Members
  • 5519 posts
  • Last active: May 17 2015 06:39 AM
  • Joined: 26 Oct 2012
Thanks jonny, I'm using it as an include in all my scripts.

I have the latest version of AutoHotkey, but missed params still give problems (I use 'e' instead of 'execute'):
e("MsgBox", , "Information", "Hmm ...")
Is it something I'm doing wrong?

jonny
  • Members
  • 2951 posts
  • Last active: Feb 24 2008 04:22 AM
  • Joined: 13 Nov 2004
If you want to use one in-between another, you can't leave it blank. This is because a parameter can only have a default value if every one after it is blank too (more details in the Functions help page). Just remember to use a blank value when you're going to use parameters after it; that is, put the quotes in even if you aren't going to use it:

e("MsgBox", "", "Information", "Hmm ...")



Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
try replacing the top portion of script with the code below:
execute(CmdLine)
{
	global r1,r2,r3,r4,r5,r6,r7

	StringGetPos, cPos, CmdLine, `,
	StringGetPos, sPos, CmdLine, %A_SPACE%

	IfGreater, sPos, 0
		IfLess, sPos, %cPos%
			cPos = %sPos%
	
	StringLeft, Command, CmdLine, %cPos%
	cPos ++
	StringTrimLeft, CmdLine, CmdLine, %cPos%
	CmdLine = %CmdLine%
	
	IfEqual, Command,
	{
		Command = %CmdLine%
		CmdLine =
	}
	
	Loop, Parse, CmdLine, `,, %A_Space%%A_Tab%
		P%A_Index% = %A_LOOPFIELD%
	
	if command not in......

this enables very simple usage for cmds from external files. like this:

loop, read, somefile.txt
execute(a_loopreadline)

besides, i think it'll solve the problem of blank params.

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


Chris
  • Administrators
  • 10727 posts
  • Last active:
  • Joined: 02 Mar 2004
To prevent the failure of the forum to word-wrap long lines, I've edited the above to have a continuation section, hopefully with ruining its functionality via typos.

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
i've done a needed fix to my code above.

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


jonny
  • Members
  • 2951 posts
  • Last active: Feb 24 2008 04:22 AM
  • Joined: 13 Nov 2004
Thanks, Rajat. I'll add it as soon as I can access it; autohotkey.net seems to be undergoing maintenance at the moment.

jonny
  • Members
  • 2951 posts
  • Last active: Feb 24 2008 04:22 AM
  • Joined: 13 Nov 2004
Alright, it's been added and the link has been fixed. I haven't tested it yet, but I'm assuming you already did, and I pasted it just as it was. Since I'm still a little foggy on the usage myself, it'd be nice if you could modify the description in the first post above and PM it to me, Rajat; if you don't have time, though, don't worry about it. Eventually I'll get around to playing with it myself.

Rajat
  • Members
  • 1904 posts
  • Last active: Jul 17 2015 07:45 AM
  • Joined: 28 Mar 2004
i'm not sure but i think i did some changes to the above code after my last post. anyways i've updated and cleaned it to a code that i'm currently using in one script.

MIA

CleanNews.in : Bite sized latest news headlines from India with zero bloat


jordis
  • Members
  • 81 posts
  • Last active: Aug 22 2014 01:56 PM
  • Joined: 30 Jul 2004
Excuse my ignorance, but why would you want to "Execute AHK code dynamically"? What are the advantages? Any practical (and plain) example?
thanks!

Robert Carnegie
  • Members
  • 54 posts
  • Last active: Mar 10 2009 05:34 PM
  • Joined: 01 Jun 2005

Excuse my ignorance, but why would you want to "Execute AHK code dynamically"? What are the advantages? Any practical (and plain) example?
thanks!


"Execute dynamically" means to construct new AHk program code while a program is running, usually in variables, and then execute the constructed command. Of course, much the same thing could be done by writing a program that creates a new script file, but that's messier.

For instance, on my hypothetical to-do list is a window manager program. Currently I have a routine that looks for a named window and then prods it every couple of seconds to come to the top - this allows me to part the window on top of the taskbar without getting covered. I intend to extend this by having it run a separate script that collects multiple window IDs and multiple commands to perform regularly on these windows - another taskbar issue is that certain events, such as the screensaver, bounce program windows away from the taskbar. So a command can be re-run to put the window back where you want it. Alternatively, one might want to program a toolbar window to move away from the mouse unless the mouse is actually on it, so that you can bounce it away from your working area on the screen.

For general use, it will be useful to have a secondary script, which the user edits, that identifies the windows that the script will operate on and the operations that will be performed. The main script then performs the programmed operations - and if I want to publish an upgrade, the main script can be replaced and the user's own secondary script probably used exactly as before.

Unfortunately I haven't published anything yet, but the principle stands ;-)

AHKnow*
  • Guests
  • Last active:
  • Joined: --
Just was playing with this. This is still very nice.