SEuBo Posted February 9, 2021 Posted February 9, 2021 (edited) Hi Folks, this is a simple example of how to generate a function with and call it during runtime (+ pass data from/to it). It is accomplished by using AutoItObject and inspired by Access AutoIt. #include <AutoItGenFuncEx.au3> $iSleepTime = 500 $oFunction = _AutoItGenFuncEx_CreateFunction("$iTreshold", _; <------ What are the Parameters? '' _; <------ What is the Sourcecode? & @LF & 'For $i = 1 to 100' _ & @LF & ' IF $i <= $iTreshold then ' _ & @LF & ' Sleep(10)' _ & @LF & ' Else' _ & @LF & ' Sleep($iSleepTime) ; slower at the end.' _ & @LF & ' EndIf' _ & @LF & '' _ & @LF & ' ToolTip("Counter:" & $i)' _ & @LF & 'Next', _ "") ; <------ What should be returned? If IsObj($oFunction) Then $oFunction.Call(Random(90, 95, 1)) EndIf There are many discussions about running "dynamic" autoit code on the internet - and there are a lot of alternatives for this. And almost always, it is absolutely not necessary to do such a thing as generating function code at runtime, because you're better off with a different program design choice. My need for this came from a very special use case. People have tried to approach this problem in several ways each with it's own set of advantages and limitations - very simple tasks can be accomplished with Execute(), Call(), Eval(), Assign(), or running source with /AutoItScriptExecuteLine or /AutoItScriptExecute, more advanced tasks can usually be tackled with multiple scripts communicating with each other via files, console streams, windows messages, tcp, dllcallbacks, etc. The most advanced discussions I've found on this included to get 'autoit function pointers', adding threads to the autoit script or copying the function into a new process, which, to my knowledge, have never been really successful, stable, or easy to use. - and this UDF is no exception because it still comes with it's limitations: For example you can't use ByRef parameters at all and global variables from the main program are just copies - but not actual references. Threads / Alternatives: Dynamic functions Is it possible to find out the memory address of a internal function and retreive the struct of it? _DllCall.au3 Callback - no external library (dll) required DotNet.au3 DotNet.au3 UDF to access .NET Framework from AutoIt Lua.au3 Embedding Lua scripts in AutoIt AssembleIt _AssembleIt() for FASM.au3 now with "Debugger" Standalone Example The goal of the standalone script is to showcase the idea & inspire people to explore AutoItObjects and the RoT. Spoiler generate function.zip How it works: Basically quite simple (not in this order:) Spoiler The generated Function Code - plus some additional lines of code - are written into a seperate file (in this example it's the File 'autoitselfmody.au3' in the @ScriptDir) and launched using @AutoItExe Data is passed from the main script to the generated file (and vice versa) using a simple Container. This container can also contain callbacks for the generated function. In this example, there is a MessageBox Method showing the Callback capabilities. A second Container is created from the generated file to pass back the generated function and the main script is notified. (in this example, the Property "ready" is changed to True) The main script can now call the generated function, pass parameters, receive Returns, etc. How it's done: Technically this is just.. Spoiler Creating a simple AutoItObjects Object "$Object_In" in the main script using _AutoItObject_Create() to pass data or functions "to" the generated script Adding a simple "ready" property to the Object. (In this example: Adding a Callback Method "MessageBox" to the object.) Registering the Object using _AutoItObjects_RegisterObject() Writing the generated File, which will be..: Getting the Container created at 1) using ObjGet() Creating a simple AutoItObjects Object "$Object_Out" using _AutoItObject_Create() to pass back the function reference Adding the generated Method to the just created Object using _AutoItObject_AddMethod() Registering the Object using _AutoItObjects_RegisterObject() (In this example: Calling the Callback of object) setting the "ready" property created at 2) to True Idling around 6) Starting the generated File 7) Waiting for the "ready" property created at 2) to be changed to True 8.) Getting the Object created at 5.2) using ObjGet 9) Calling the Function via the object method created at 5.3) Example Script Spoiler expandcollapse popup#include <AutoItObject.au3> _AutoItObject_Startup() ; Container for passing data, callbacks, etc. $oObject_In = _AutoItObject_Create() _AutoItObject_RegisterObject($oObject_In, 'AutoItTest.SelfMody.In') _AutoItObject_AddProperty($oObject_In, 'ready') ; Example: Callback-Method _AutoItObject_AddMethod($oObject_In,"MessageBox", "MessageBox") ; Example: Call function in main script in main script (nothing special yet) $oObject_In.MessageBox("1) Regular call of function from within the same script") ; generate external function Make_external_function() ; call external function: Do Sleep(100) Until $oObject_In.ready $oObject_Out = ObjGet("AutoItTest.SelfMody.Out") $oObject_Out.some_external_function("3) call of function in external (generated) Script") Func MessageBox($oSelf, $sText) MsgBox(0,"",$sText) EndFunc Func Make_external_function() $sSourceCode = '' _ &@LF& '#include <AutoItObject.au3>' _ &@LF& '_AutoItObject_StartUp()' _ &@LF& '$oObject_In = ObjGet("AutoItTest.SelfMody.In")' _ &@LF& '' _ &@LF& '$oObject_Out = _AutoItObject_Create()' _ &@LF& '_AutoItObject_AddMethod($oObject_Out,"some_external_function", "some_external_function")' _ &@LF& '_AutoItObject_RegisterObject($oObject_Out, "AutoItTest.SelfMody.Out")' _ &@LF& '' _ &@LF& '$oObject_In.MessageBox("2) Callback of Function from external script")' _ &@LF& '$oObject_In.ready = True' _ &@LF& '' _ &@LF& 'While Sleep(100)' _ &@LF& 'WEnd' _ &@LF& '' _ &@LF& 'Func some_external_function($oSelf, $vParam)' _ &@LF& ' MsgBox(0,"some_external_function",$vParam)' _ &@LF& ' Exit' _ &@LF& 'EndFunc' FileDelete(@ScriptDir & '\autoitselfmody.au3') FileWrite(@ScriptDir & '\autoitselfmody.au3', $sSourceCode) Run(StringFormat('%s /AutoIt3ExecuteScript "%s"', @AutoItExe, @ScriptDir & '\autoitselfmody.au3'),@ScriptDir) EndFunc Output: FYI : the "generated" File looks like this - the generated part would be 'MsgBox(0,"some_external_function",$vParam)'. The rest is just loading the objects in & out. Spoiler #include <AutoItObject.au3> _AutoItObject_StartUp() $oObject_In = ObjGet("AutoItTest.SelfMody.In") $oObject_Out = _AutoItObject_Create() _AutoItObject_AddMethod($oObject_Out,"some_external_function", "some_external_function") _AutoItObject_RegisterObject($oObject_Out, "AutoItTest.SelfMody.Out") $oObject_In.MessageBox("2) Callback of Function from external script") $oObject_In.ready = True While Sleep(100) WEnd Func some_external_function($oSelf, $vParam) MsgBox(0,"some_external_function",$vParam) Exit EndFunc Simple UDF "AutoItGenFunc" The goal of the UDF is to have an easy way for beginners and lazy people to use way to allow "complex" AutoIt Coding to be executed during Runtime. Spoiler /Edit: I've created a ready-to use UDF to generate functions. Maybe you want to use that instead. See the AutoItGenFunc.au3 Archive attached AutoItGenFunc.zip AutoItGenFunc.au3 - the simple UDF Spoiler expandcollapse popup#include-once #include <File.au3> #include <AutoItObject.au3> Func _AutoItGenFunc_CreateFunction($sParameters, $sCoding, $sReturn = "") Local Static $fInitialized = False If Not $fInitialized Then _AutoItObject_Startup() $fInitialized = True EndIf Local $sUniqueID = StringMid(_TempFile(@ScriptDir, "", "", 9), StringLen(@ScriptDir) + 2, -2) If $sParameters <> '' Then $sParameters = ', ' & $sParameters $sSourceCode = '' _ & @LF & '#include <AutoItObject.au3>' _ & @LF & '_AutoItObject_StartUp()' _ & @LF & '$oObject_Main = ObjGet("_AutoItGenFunc.' & $sUniqueID & '.Main")' _ & @LF & '' _ & @LF & '$oObject_Sub = _AutoItObject_Create()' _ & @LF & '_AutoItObject_AddProperty($oObject_Sub,"done", "")' _ & @LF & '_AutoItObject_AddMethod($oObject_Sub,"call", "_AutoItGenFunc__DynamicFunction")' _ & @LF & '_AutoItObject_RegisterObject($oObject_Sub, "_AutoItGenFunc.' & $sUniqueID & '.Sub")' _ & @LF & '' _ & @LF & '$oObject_Main.ready = True' _ & @LF & 'Do ' _ & @LF & ' Sleep(100)' _ & @LF & 'Until $oObject_Sub.done Or Not ProcessExists(' & @AutoItPID & ')' _ & @LF & '' _ & @LF & 'Func _AutoItGenFunc__DynamicFunction($oSelf' & $sParameters & ')' _ & @LF & $sCoding _ & @LF & ' $oSelf.done = True' _ & @LF & ' Return ' & $sReturn _ & @LF & 'EndFunc' _ & @LF & '' $oObject_Main = _AutoItObject_Create() _AutoItObject_AddProperty($oObject_Main, 'ready') _AutoItObject_RegisterObject($oObject_Main, "_AutoItGenFunc." & $sUniqueID & ".Main") FileWrite(@ScriptDir & '\' & $sUniqueID, $sSourceCode) $iPID = Run(StringFormat('%s /AutoIt3ExecuteScript "%s"', @AutoItExe, @ScriptDir & '\' & $sUniqueID), @ScriptDir) Do Sleep(100) Until $oObject_Main.ready; OR not ProcessExists($iPID) $oObject_Sub = ObjGet("_AutoItGenFunc." & $sUniqueID & ".Sub") If Not IsObj($oObject_Sub) Then Return SetError(@error, @extended, Null) Return $oObject_Sub EndFunc ;==>_AutoItGenFunc_CreateFunction You 1)Create a function using $oFunction = _AutoItGenFunc_CreateFunction($parameters, $coding, $returnstatement), then call the "call(...)" method of your function object. The call()-method of the returned Function Object will have the parameters you defined when calling _AutoItGenFunc_CreateFunction. Usage Example #1 of AutoItGenFunc: Spoiler #include <AutoItGenFunc.au3> $oFunction = _AutoItGenFunc_CreateFunction( _ "$iMsgBoxFlag, $sTitle, $sText", _ ; <------ What are the Parameters? "MsgBox($iMsgBoxFlag, $sTitle, $sText)", _ ; <------ What is the Sourcecode? "") ; <------ What should be returned? If IsObj($oFunction) Then MsgBox(0, '', 'Example 1 returned: ' & $oFunction.Call(64, 'Some great title', 'Some philosophical text') & '... because it doesnt have a return') EndIf Output: Usage Example #2 of AutoItGenFunc: Spoiler #include <AutoItGenFunc.au3> $oFunction = _AutoItGenFunc_CreateFunction("$sSendText", _ ; <------ What are the Parameters? 'Run("notepad.exe")' _ ; <------ What is the Sourcecode? & @LF & 'Local $hWnd = WinWait("[CLASS:Notepad]", "", 10)' _ & @LF & 'Send("Todays time/date is {F5}{ENTER}")' _ & @LF & '' _ & @LF & 'Send("Parameter $sSendText = " & $sSendText)' _ ; <- fyi: parameter used here & @LF & '$vRandom = Random(1,100,1)' _ ; <- fyi: return value set here & @LF & '' _ & @LF & 'WinClose($hWnd)' _ & @LF & 'WinWaitActive("[CLASS:#32770]")' _ & @LF & 'Sleep(500)' _ & @LF & 'Send("{TAB}")', _ "$vRandom") ; <------ What should be returned? If IsObj($oFunction) Then MsgBox(0, '', 'Example 2 returned a random number: ' & $oFunction.Call("This is written to Notepad")) EndIf Output: Extended UDF "AutoItGenFuncEx" The goal of the extended UDF is to have an easy to use way for beginners and lazy people to allow even more "complex" AutoIt Coding (callbacks) to be executed during Runtime. Spoiler AutoItGenFuncEx_v3.zip I've also created AutoItGenFuncEx.au3, which allows direct 'access' to global variables and functions (see below) in the main script. Direct access to global variables means: the values of used global variables are copied into the object before the function is executed. Please see Example #3. Global variables can be changed inside the function and are copied back before return.Note: Changes to global variables may not be reflected in Callback Functions called from your generated function (as of now). This behaviour is subject to change. AutoItGenFuncEx allows callbacks to the main script. Please see Example #4. Functions are therefore wrapped into a Custom function __AutoItGenFuncExWrapped__YOUFUNCTIONNAMEHERE that have an additional parameter $__oSelf.Note: To enable callbacks a line "#AutoItGenFunc_AllowCallbacks=true" somewhere in your script is required. This will make the UDF look for certain #include- and #AutoIt3Wrapper_Res_File_Add-Directives in your main script file. It will add your function definitions (names & parameters) to your program resources, plus include a wrapper file to which adds an additional parameter for the AutoItObject-Reference to the callback-functions. Include files are resolved automatically but can be Excluded by adding a line #AutoItGenFunc_SkipInclude=true in the respective include file. AutoItGenFuncEx - Example 1 - Simple Messagebox: Spoiler #include <AutoItGenFuncEx.au3> ; Step 1) Create a Function: $oFunction = _AutoItGenFuncEx_CreateFunction( _ "$iMsgBoxFlag, $sTitle, $sText", _ ; <------ What are the Parameters? "MsgBox($iMsgBoxFlag, $sTitle, $sText)", _ ; <------ What is the Sourcecode? "") ; <------ What should be returned? ; Step 2) Check, if the function was created: If IsObj($oFunction) Then ; Step 3) Call the function. (-> Parameters of call() are defined in line 5) $vReturnValue = $oFunction.Call(64, 'Some great title', 'Some philosophical text') ; Step 4) Display the return value. (-> Which is defined in line 7) MsgBox(0, '', 'Example 1 returned: ' & $vReturnValue & '... because it doesnt have a return') EndIf AutoItGenFuncEx - Example 2 - Write Text in Notepad: Spoiler #include <AutoItGenFuncEx.au3> ; Step 1) Create a Function: $oFunction = _AutoItGenFuncEx_CreateFunction( _ "$sSendText", _ ; <------ What are the Parameters? & '' _ & @LF & 'Run("notepad.exe")' _ ; <------ What is the Sourcecode? & @LF & 'Local $hWnd = WinWait("[CLASS:Notepad]", "", 10)' _ & @LF & 'Send("Todays time/date is {F5}{ENTER}")' _ & @LF & '' _ & @LF & 'Send("Parameter $sSendText = " & $sSendText)' _ ; <- fyi: parameter used here & @LF & '$vRandom = Random(1,100,1)' _ ; <- fyi: return value set here & @LF & '' _ & @LF & 'WinClose($hWnd)' _ & @LF & 'WinWaitActive("[CLASS:#32770]")' _ & @LF & 'Sleep(500)' _ & @LF & 'Send("{TAB}")', _ "$vRandom") ; <------ What should be returned? ; Step 2) Check, if the function was created: If IsObj($oFunction) Then ; Step 3) Call the function. (-> Parameters of call() are defined in line 5) $vReturnValue = $oFunction.Call("This is written to Notepad") ; Step 4) Display the return value. (-> Which is defined in line 18, and set in line 12) MsgBox(0, '', 'Example 2 returned a random number: ' & $vReturnValue) EndIf AutoItGenFuncEx - Example 3 - Share global variables: Spoiler expandcollapse popup#include 'AutoItGenFuncEx.au3' $hGUI = GUICreate("Example 3") $hButton = GUICtrlCreateButton("Click me",0,0,400, 400) GUICtrlSetFont(-1, 36) GUISetState() $Global_variable_in_main = "not a parameter, but global variable" While 1 $nMsg = GUIGetMsg() Switch $nMsg Case -3 Exit Case $hButton ; Step 1) Create a Function: $oRandom = _AutoItGenFuncEx_CreateFunction( _ '' & _ ; ----- Parameters: "$iFrom = 0, $iTo = 100", _ '' _ ; ----- Sourcecode: & @LF & "MsgBox(0,'','$Global_variable_in_main is: ' & @LF & @LF & $Global_variable_in_main)" _ & @LF & "If $hGUI <> '' Then " _ & @LF & " MsgBox(0,'','and $hGUI is: ' & $hGUI)" _ & @LF & 'EndIf' _ & @LF & 'WinMove($hGUI, "", Random(0, @DesktopWidth - 300, 1), Random(0, @DesktopHeight - 300, 1))' _ & @LF & 'Sleep(10)', _ '' & _ ; ----- Return: "Random($iFrom, $iTo, 1)") ; Step 2) Check, if the function was created: If IsObj($oRandom) Then ; Step 3) Call the function. (-> Parameters of call() are defined in line 22) $iRandomValue = $oRandom.call(1, 100) ; Step 4) Display the return value. (-> Which is defined in line 30) GUICtrlSetData($hButton, $iRandomValue) EndIf EndSwitch WEnd AutoItGenFuncEx - Example 4 - Callbacks into main script: Spoiler expandcollapse popup#include <AutoItGenFuncEx.au3> #include <MsgBoxConstants.au3> #AutoItGenFunc_AllowCallbacks=yes ; <----- this enables callbacks. script will add compiler-directives and restart on first launch. Make sure to launch script at least once uncompiled to allow those source code updates. Global $hGUI, $say_hi = 'hello' ; Step 1) Create a Function: $oFunction = _AutoItGenFuncEx_CreateFunction( "$sTitle", _ ; Parameters "" _ &@LF& "$iMsgBox = MsgBox(4, $sTitle, 'very callback.') " _ ; parameter $sTitle defined in line 8 &@LF& " " _ &@LF& "If $iMsgBox = 6 Then " _ &@LF& " _some_callback('wow', $say_hi & ' this is doge')" _ ; _some_callback() is defined in line 41 &@LF& " $say_hi = 'oh, hi doge' " _ ; variable $say_hi is defined as Global in line 5 &@LF& "Else " _ &@LF& " $say_hi = 'sad' " _ &@LF& "EndIf " _ ) ; ; Step 2) Check, if the function was created: If IsObj($oFunction) Then ; Step 3) Call the function. (-> Parameters of call() are defined in line 9) $oFunction.Call('much function') EndIf ; This variable $say_hi is changed inside the generated function MsgBox(0,"", $say_hi) ; This handle "$hGUI" is set in line 42, by a function "_some_callback" which is called from the generated function (line 12) If IsHWnd($hGUI) Then Do Sleep(10) Until GUIGetMsg() = -3 GUIDelete($hGUI) EndIf Func _some_callback($sGUITitle, $sGUIText) $hGUI = GUICreate($sGUITitle, 400, 100, 100, 300) GUICtrlCreateLabel($sGUIText, 0, 0, 400, 100) GUICtrlSetFont(-1, 36) GUISetState() WinSetOnTop($hGUI, '', 1) EndFunc ;==>_some_callback Output: AutoItGenFuncEx - Example 5 - Keeping functions alive for performance: Spoiler #include <AutoItGenFuncEx.au3> #include <Date.au3> #include <MsgBoxConstants.au3> Global $sToolTip ; Step 1) Create a Function: $oFunction = _AutoItGenFuncEx_CreateFunction( _ "$iFrom = -999, $iTo = 999", _ "ToolTip('Generated function says: ' & $sToolTip)", _ "Random($iFrom, $iTo , 1)") For $i = 1 To 100 $sToolTip = _NowTime() & "." & @MSEC $iReturn = $oFunction.Call(1, 100, True) ; all functions have an additional option parameter $fKeepAlive at the end; if set to True, function will not self-release after first call. ;~ ConsoleWrite("Random value: " & $iReturn & @CRLF) ToolTip("Random value: " & $iReturn , 400, 400) Next $oFunction.done = True ; release function MsgBox(0, "", "The function will be released now.") ; dont try this: $oFunction.Call() Download within the corresponding Spoilers, or find version history below: Update 17.02.2021: - added parameter to keep functions alive, see Example #5 - Global Variables are now changeable and copied back into the main script, see Updated Example #4. - added $oFunction.Source which stores the AutoIt-Source of the generated file for debugging purposes. - better handling of global vars and funcs - added logic for also resolving global vars and functions in included files. - added #AutoItGenFuncEx_SkipInclude directive to indicate that a include should not be "wrapped", thus not being callable from a generated function. AutoItGenFuncEx_v3.zip Update 15.02.2021: - access global variables (read-only) and callback functions from main program. - added #AutoItGenFuncEx_AllowCallbacks directive to indicate that functions in the main script should be wrapped into callback-enabled functions. See Example #4. AutoItGenFuncEx_v2.zip Initial Post: generate function.zip AutoItGenFunc.zip I did not find any easier solution for sharing data and functions between scripts yet, so this is my dirty hack. Maybe it's useful for someone with the same problem. I would also be happy if someone would point out alternatives or improvements. I feel like there is potential. Edited February 17, 2021 by SEuBo v3, Example 4 updated, Example 5 added Gianni 1 AutoIt Examples/UDF's:Generate Function at Runtime using IRunningObjectTable / AutoItObjectVery Simple Inter-Process Communication (using AutoItObject Pure AutoIt)
junkew Posted February 11, 2021 Posted February 11, 2021 I am missing the why I would do it this way and not compile directly your code with everything in it. anyway check the eval, execute, assign, call in the helpfile Example of usage besides the help example it interprets a simple multiline string as a micro language (no loop constructs supported) #include <MsgBoxConstants.au3> func moreDynamic($str) consolewrite($str) EndFunc ;Assign function to variable $f=MsgBox $f($MB_SYSTEMMODAL, "Title","dynamic function") $f=moreDynamic $f("just some text") ;Call function $strMultiLine = "msgbox 0 title fromstring'" & @Crlf $strMultiLine &= "moredynamic texttoshowdynamic" & @Crlf $strMultiLine &= "consolewrite texttoshowdynamic2console" & @Crlf $arrLines=stringsplit($strMultiLine, @crlf) dim $i for $i=0 to ubound($arrLines)-1 $fArray=stringsplit($arrLines[$i], " ") $parCount=ubound($farray)-1 consolewrite($fArray[1] & $parcount & @crlf) if $parCount = 0 then call($fArray[1]) if $parCount = 1 then call($fArray[1],$fArray[2],$fArray[3]) if $parCount = 2 then call($fArray[1],$fArray[2]) if $parCount = 3 then call($fArray[1],$fArray[2],$fArray[3]) if $parCount = 4 then call($fArray[1],$fArray[2],$fArray[3],$fArray[4]) Next FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
SEuBo Posted February 11, 2021 Author Posted February 11, 2021 (edited) Hi, Because your Example wouldn't allow Variable assignments, Loops, If-Statements, etc. #include <AutoItGenFunc.au3> $oFunction = _AutoItGenFunc_CreateFunction("", _ ; <------ What are the Parameters? '' _ ; <------ What is the Sourcecode? & @LF & 'For $i = 1 to 100' _ & @LF & ' IF $i < 50 then ' _ & @LF & ' Sleep(100)' _ & @LF & ' Else' _ & @LF & ' Sleep(10) ; faster at the end.' _ & @LF & ' EndIf' _ & @LF & '' _ & @LF & ' ToolTip("Counter:" & $i)' _ & @LF & 'Next', _ "") ; <------ What should be returned? If IsObj($oFunction) Then $oFunction.Call() EndIf oh and the "why" is: I have a Complex application and users are supposed to create business objects and corresponding logic by themselfes supported by GUI easy AutoItObjects based Scripting. Logic is supposed to be entered and executed during runtime. This is my workaround until I can understand how to hook into IDispatch deep enough to dynamically load the coding directly into an AutoItObject-Object or something. This is nothing I intend to use on daily basis, but I still found it interesting enough to share, since most discussions about dynamic functions in Autoit end up with Execute(), Assign(), Eval() and it's limitations. Cheers, Edited February 11, 2021 by SEuBo AutoIt Examples/UDF's:Generate Function at Runtime using IRunningObjectTable / AutoItObjectVery Simple Inter-Process Communication (using AutoItObject Pure AutoIt)
junkew Posted February 11, 2021 Posted February 11, 2021 My point was more that you still need the AutoIt compiler to run the script thats outside on the filesystem. The examples I gave are able to run without compiler and yes biggest missing things are loops, if statements. But anyway : #pragma compile(AutoItExecuteAllowed, true) would allow me to run any non compiled AutoIt file. Your example looks fine but just trying to understand when to use it FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets
SEuBo Posted February 11, 2021 Author Posted February 11, 2021 (edited) Hey! As I said, it's a very very special usage scenario and I never had to use such a thing within the all my autoit life - up until now. 5 hours ago, junkew said: My point was more that you still need the AutoIt compiler to run the script thats outside on the filesystem. https://www.autoitscript.com/autoit3/docs/intro/running.htm Run a script using another compiled script: Compiled.exe [/ErrorStdOut] /AutoIt3ExecuteScript file [params ...] Execute another AutoIt script file from a compiled AutoIt3 executable. Compiled.exe [/ErrorStdOut] /AutoIt3ExecuteLine "command line" Execute one line of code as with AutoIt3.exe above. This means that there is no need to have a copy of AutoIt3.exe in addition to the compiled file - the interpreter stub of the compiled file will replace it. So as long as there is at least one compiled script available, other AutoIt scripts can be run without the need to have AutoIt3.exe on the machine., either pre-installed or added via FileInstall. that is, if the script is compiled with #pragma compile(AutoItExecuteAllowed, true) as you stated, yes. but that's the default. Edited February 12, 2021 by SEuBo AutoIt Examples/UDF's:Generate Function at Runtime using IRunningObjectTable / AutoItObjectVery Simple Inter-Process Communication (using AutoItObject Pure AutoIt)
Moderators Melba23 Posted February 11, 2021 Moderators Posted February 11, 2021 SEuBo, Quote if the script is compiled with #pragma compile(AutoItExecuteAllowed, true) as you stated, yes. but that's the default. No, the default is NOT to allow compiled scripts to run other scripts - from the Help file: Quote However, the executable must have been compiled with the #pragma compile(AutoItExecuteAllowed, True) directive as the default setting does not permit use of the /AutoItExecuteScript or /AutoItExecuteLine parameters. M23 SEuBo 1 Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind Open spoiler to see my UDFs: Spoiler ArrayMultiColSort ---- Sort arrays on multiple columnsChooseFileFolder ---- Single and multiple selections from specified path treeview listingDate_Time_Convert -- Easily convert date/time formats, including the language usedExtMsgBox --------- A highly customisable replacement for MsgBoxGUIExtender -------- Extend and retract multiple sections within a GUIGUIFrame ---------- Subdivide GUIs into many adjustable framesGUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView itemsGUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeViewMarquee ----------- Scrolling tickertape GUIsNoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxesNotify ------------- Small notifications on the edge of the displayScrollbars ----------Automatically sized scrollbars with a single commandStringSize ---------- Automatically size controls to fit textToast -------------- Small GUIs which pop out of the notification area
SEuBo Posted February 12, 2021 Author Posted February 12, 2021 (edited) On 2/11/2021 at 8:09 PM, junkew said: Your example looks fine but just trying to understand when to use it /Edit: I've updated the first post in regard to this. The usage scenario is create & call a function which parameters and behaviour is unkown during compile time (or startup) and can also not be determined by algorithms, because it is supposed to be programmed while the application is running. I am developing an AutoIt based ERP system together with a small local business as a prototype/first customer help them reduce costs. The entire application, and all data / functions are encapsulated in Objects (- from here on I use the word "objects" equivalent to "classes". ). There are - System objects (e.g. "Application", "Database", "ObjectBuilder", "Printer", "Mail", etc.) and - Business objects (e.g. "Material", "Materialprice", "Customer", "Salesorder", "Material Text", "Contract", "Invoice", "ContractReleaseOrder", etc.). The system objects are fixed and encapsulate everything that runs "in the background" and some very generic functionality. There will be a standard set of business objects and templates, but in general, business objects, their relations and their logics are to be created during runtime - by the user. This will be a heavily UI-guided process. Also, users are supposed to write Scripts "just-in-time", while there are looking at some data inside the application. Those Scripts shall have access to the whole Application: the screens, the data, the other objects, AutoIt Functions, the neat and the ugly bits. There is nothing worse than having a functionality somewhere that is doing exactly what you need, but you can't call it. At the moment, the Business Objects are created manually (XML files with their definition and au3 files with method coding). After those files are added (and an #include-statement was added to a collective include), I have to restart my application. Otherwise I can not access the just created include. And this is where my problem comes from: The Function sourcecode is entered by the user and it can only be called in the current application after restart (which is bad, when you already entered data on the screen, but also want a new script to run). There are a lot of workarounds for stuff like this - exposing data & functions via API and defined interfaces, etc., - NOT letting users enter code and mess with stuff, - using languages that are better suited.. But I chose AutoIt because it is amazing and I want it to be the scripting language inside my AutoIt Application. As I said: very special use-case. Just for clarification Edited February 14, 2021 by SEuBo AutoIt Examples/UDF's:Generate Function at Runtime using IRunningObjectTable / AutoItObjectVery Simple Inter-Process Communication (using AutoItObject Pure AutoIt)
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