Uten Posted March 14, 2006 Share Posted March 14, 2006 (edited) Demonstration of a simple Autoit script plug-in architecture.I have a fascination for distributed computing. Collecting the power of spare CPU cycles within a organization or on computers administrated by people willing to donate spare resources (and electricity).When I took a look at Blue Security "opt out spam client", I realized that AutoIt could be a very strong contender if you need to build a quick distributed computing system. The first step towards a simple distributed computing framework utilizing AutoIts compact core language and a selection of powerful functions, was do collect the code fragments needed to support a plug-in architecture.This is what I came up with:mainProg.au3: Basically a simple installation program. It has to contain the Autoit compiler, your application scripts and probably some default plug-ins.runner.au3: The application script. It will be modified and compiled by mainProg.au3 to use the plug-ins (default, user-modified or downloaded from the net).plugin.au3: A default plug-in used to demonstrate "prof of concept".I also defined a api provided by the runner (implemented in runner.au3). The api can be used by plug-ins. apiMsg( $argMsg ): A message function.$apiVersion: A global variable containing a version number.To let the runner know how to use the plug-in the plug-in has to implement a specific interface. In this case it is rather simple:* IRun(): Called by runner to run plug-in code.* ITerminate(): Called by runner to lett plug-in clean up and terminate (ex: external processes)So here goes. A the simplest working plug-in sample. NOTE: You have to modify paths to reflect your development machine (necessary places should be marked with TODO:); PURPOSE: Demonstarting a Autoit Plug-in architecture. ; This is the plugin used by runner.au3. It could be ; downloaded from the net or modified by a user. ; FILENAME: plugin.au3 ; CREATED BY: Uten ; HOME: ; CHANGE LOG: ;---------------------------------------------------------------------- ; Uten 14 mar 2006: Published ; ;---------------------------------------------------------------------- Func IRun() apiMsg("Hello from plug-in" & @CRLF & "I have done my work.:D") EndFunc Func ITerminate() msgbox(0,"Plug-in sample, in plug-in", "Terminating" & @CRLF & "NOTE: $apiVersion:=" & $apiVersion & @CRLF & "I have cleand up my act") EndFunc; PURPOSE: Demonstarting a Autoit Plug-in architecture. ; This is the real application. Define api to be used by ; plug-ins here. ; FILENAME: runner.au3 ; CREATED BY: Uten ; HOME: ; CHANGE LOG: ;---------------------------------------------------------------------- ; Uten 14 mar 2006: Published ; ;---------------------------------------------------------------------- Global $apiVersion="1.0"; Global variable accessable from the Func apiMsg($argMsg) msgbox(0, "Plug-in sample, runner prog", $argMsg) EndFunc ; Call to a function that must exist in the plugin! IRun() sleep(2000) ; Call ITerminate to lett the plugin clean up. ITerminate() Exitexpandcollapse popup; PURPOSE: Demonstrating a Autoit Plug-in architecture. ; This is the main application whos purpose is to configure ; and build the real application. ; FILENAME: mainProg.au3 ; CREATED BY: Uten ; HOME: ; CHANGE LOG: ;---------------------------------------------------------------------- ; Uten 14 mar 2006: Published ; ;---------------------------------------------------------------------- dim $mainProg = "\runner.au3" dim $plugin = "plugin.au3" dim $targetAtoit = "\_au3.exe"; Use uniqe name to avoid conflicts. ;---------------------------------------------------------------------- ; Installer section ; fileinstall will package the files at compiletime and unpack them at ; run time. ; NOTE: fileinstall must have absolute path at compiletime. Variables ; are not evaluated. ; TODO: Modify location of AutoIt3.exe fileinstall("C:\Program Files\AutoIt3\beta\AutoIt3.exe", @TempDir & _ $targetAtoit, 1) fileinstall("runner.au3", @TempDir & $mainProg,1) ; NOTE: You could download "plugin" files from the net rather than ; writing the default, or lett the user write one, like this. fileinstall("plugin.au3", $plugin,0);0->Do not overwrite? ;---------------------------------------------------------------------- ; Modify necesary filesto relect new plugins, locations and such ; Add "plugin" include files to the end of the "main" prog. The "main" ; prog should be fresh each time. $file = FileOpen(@TempDir & $mainProg, 1) FileWrite($file, "#include "& Chr(34) & @ScriptDir & "\" & _ $plugin & Chr(34) & @CRLF) FileClose($file) ;---------------------------------------------------------------------- ; Compile the new program. dim $cmd= chr(34) & @TempDir & $targetAtoit & chr(34) & _ " /AutoIt3ExecuteScript " & chr(34) & @TempDir & _ $mainProg & chr(34) ;---------------------------------------------------------------------- ; Run the new program. This will appear in taskmanager as a new PID. RunWait($cmd, @TempDir) ;---------------------------------------------------------------------- ; Clean up unpacked files if you want to. They will be unpacked again ; next time. FileDelete(@TempDir & $mainProg) FileDelete(@TempDir & $targetAtoit)Try it out.Run mainProg.exe. This will create the default version of the program. A modifiable plug-in (plugin.au3) will be created in the same folder as you run mainProg.exe from. This file will not be replaced the next time you run mainProg.exe.Now lets modify plugin.au3:Func ITerminate() apiMsg("Terminating" & @CRLF & "NOTE: $apiVersion:=" & $apiVersion & @CRLF & "Ready to terminate.") EndFuncAnd run mainProg.exe again.If your modifications were successful the user experience of mainProg.exe should change.When you design you next killer application you might want to consider:How can you prevent users from tampering with plug-ins you do not want them to touch?How will errors in user-modified scripts be handled?Is it possible to have multiple plugins. Say, load all plugins from a directory. (The demonstrated architecture only suports one plugin file).Hopefully this little sample will give you a head start and inspiration to create the next modifiable, and possibly distributed, killer application.Happy codingplugin_architecture.zip Edited March 14, 2006 by Uten Please keep your sig. small! Use the help file. Search the forum. Then ask unresolved questions :) Script plugin demo, Simple Trace udf, TrayMenuEx udf, IOChatter demo, freebasic multithreaded dll sample, PostMessage, Aspell, Code profiling Link to comment Share on other sites More sharing options...
Nuffilein805 Posted March 14, 2006 Share Posted March 14, 2006 nice 1, but maybe i use the wrong beta - where do you find apiMsg? btw thanks for the ideas i just found a way of leaving my progs on just 1 pc :) my little chatmy little encryption toolmy little hidermy unsafe clickbot Link to comment Share on other sites More sharing options...
Uten Posted March 14, 2006 Author Share Posted March 14, 2006 Outch, I have used the same file twice. . Realy sorry about that. The attached file has what you need to compile the sample. It should work with version 3.1.1 (acka. does not need beta). I'l corect the first post asap. Regards Uten Please keep your sig. small! Use the help file. Search the forum. Then ask unresolved questions :) Script plugin demo, Simple Trace udf, TrayMenuEx udf, IOChatter demo, freebasic multithreaded dll sample, PostMessage, Aspell, Code profiling Link to comment Share on other sites More sharing options...
DaLiMan Posted April 18, 2006 Share Posted April 18, 2006 This is a really good idea for scripts which are used by different users with different rights or needs. Only problem I have is that AutoIt must be installed. Which is not the case for most users........ Could there be a way like a Mainscript and then plugins in say .au3 format which can still be used by the Mainscript? (I hope you understand.....) PS: I really like your example!! Link to comment Share on other sites More sharing options...
neogia Posted April 18, 2006 Share Posted April 18, 2006 You don't need to have AutoIt installed, just run this line when running an uncompiled .au3 file Run(@AutoItExe & ' /AutoIt3ExecuteScript "' & $PathToFile & '"') Also, Uten, I like your idea for distributed computing in AutoIt. I've developed two functions that work well to pack and unpack variables for sending across a network, the internet, etc. Take a look: expandcollapse popup;=============================================================================== ; ; Function Name: _PackVarToStr() ; Description: Packs a variable into a string form for sending to another ; script. Maintains array integrity up to 4 dimensions. ; Also supports nested arrays inside array elements. ; Parameter(s): $vPackVar = Variable to be packed into a string. ; NOTE: Variables of type Object or DllStructs are not yet ; supported. ; Return Value(s): Returns packed string to be unpacked by _UnpackStrToVar() ; Author(s): Ben Brightwell ; ;=============================================================================== Func _PackVarToStr(ByRef $vPackVar) Local $iNumDims = UBound($vPackVar, 0); Number of dimensions of $vPackVar Local $sVarStr = "$[" & $iNumDims & "]$"; Return string of packed variable Local $iCounter1 = ""; Nested Counter Local $iCounter2 = ""; Nested Counter Local $iCounter3 = ""; Nested Counter Local $iCounter4 = ""; Nested Counter For $i = 1 To $iNumDims $sVarStr &= "$[" & UBound($vPackVar, $i) & "]$" Next Select Case $iNumDims == 0 If $vPackVar == "" Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= $vPackVar EndIf Case $iNumDims == 1 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 If $vPackVar[$iCounter1] == "" And UBound($vPackVar[$iCounter1], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1]) EndIf Next Case $iNumDims == 2 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 For $iCounter2 = 0 To UBound($vPackVar, 2) - 1 If $vPackVar[$iCounter1][$iCounter2] == "" And UBound($vPackVar[$iCounter1][$iCounter2], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2]) EndIf Next Next Case $iNumDims == 3 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 For $iCounter2 = 0 To UBound($vPackVar, 2) - 1 For $iCounter3 = 0 To UBound($vPackVar, 3) - 1 If $vPackVar[$iCounter1][$iCounter2][$iCounter3] == "" And UBound($vPackVar[$iCounter1][$iCounter2][$iCounter3], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2][$iCounter3]) EndIf Next Next Next Case $iNumDims == 4 For $iCounter1 = 0 To UBound($vPackVar, 1) - 1 For $iCounter2 = 0 To UBound($vPackVar, 2) - 1 For $iCounter3 = 0 To UBound($vPackVar, 3) - 1 For $iCounter4 = 0 To UBound($vPackVar, 4) - 1 If $vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4] == "" And UBound($vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4], 0) == 0 Then $sVarStr &= "$[0]$<nil>" Else $sVarStr &= _PackVarToStr($vPackVar[$iCounter1][$iCounter2][$iCounter3][$iCounter4]) EndIf Next Next Next Next EndSelect Return $sVarStr EndFunc ;==>_PackVarToStr expandcollapse popup;=============================================================================== ; ; Function Name: _UnpackStrToVar() ; Description: Turns a packed variable string back into a variable. ; Parameter(s): $sVarStr = A packed variable string as returned by _PackVarToStr() ; Return Value(s): Variable of type that was passed to _PackVarToStr() ; Author(s): Ben Brightwell ; ;=============================================================================== Func _UnpackStrToVar(ByRef $sVarStr) Local $aiNumDims = StringRegExp($sVarStr, '(?:\$\[)(\d*)(?:\]\$)(\#)', 1) Local $aiDimSizes[1]; To contain the size of each dimension as passed through $sVarStr Local $aiDimSize = ""; To contain the size of current dimension and string position for stripping Local $avRetArr[1]; To be redimensioned and have $sVarStr parsed and stored into as an array Local $avElementStr = ""; To contain each element as a string as it is parsed from $sVarStr If IsArray($aiNumDims) Then $sVarStr = StringTrimLeft($sVarStr, $aiNumDims[1]) If $aiNumDims[0] > 0 Then ReDim $aiDimSizes[$aiNumDims[0]] For $iCounter1 = 0 To $aiNumDims[0] - 1 $aiDimSize = StringRegExp($sVarStr, '(?:\$\[)(\d*)(?:\]\$)(\#)', 1) $aiDimSizes[$iCounter1] = $aiDimSize[0] $sVarStr = StringTrimLeft($sVarStr, $aiDimSize[1]) Next EndIf Select Case $aiNumDims[0] == 0 If StringInStr($sVarStr, "$[") Then $avElementStr = StringRegExp($sVarStr, '(.*?)(\#)(?:\$\[)', 1) $sVarStr = StringTrimLeft($sVarStr, $avElementStr[1]) If $avElementStr[0] <> "<nil>" Then Return $avElementStr[0] Else Return "" EndIf Else If $sVarStr == "<nil>" Then Return "" Else Return $sVarStr EndIf EndIf Case $aiNumDims[0] == 1 ReDim $avRetArr[$aiDimSizes[0]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 $avRetArr[$iCounter1] = _UnpackStrToVar($sVarStr); In case element holds another array (Recursive) Next Case $aiNumDims[0] == 2 ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 For $iCounter2 = 0 To $aiDimSizes[1] - 1 $avRetArr[$iCounter1][$iCounter2] = _UnpackStrToVar($sVarStr); In case element holds another array (Recursive) Next Next Case $aiNumDims[0] == 3 ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]][$aiDimSizes[2]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 For $iCounter2 = 0 To $aiDimSizes[1] - 1 For $iCounter3 = 0 To $aiDimSizes[2] - 1 $avRetArr[$iCounter1][$iCounter2][$iCounter3] = _UnpackStrToVar($sVarStr); In case element holds another array (Recursive) Next Next Next Case $aiNumDims[0] == 4 ReDim $avRetArr[$aiDimSizes[0]][$aiDimSizes[1]][$aiDimSizes[2]][$aiDimSizes[3]] For $iCounter1 = 0 To $aiDimSizes[0] - 1 For $iCounter2 = 0 To $aiDimSizes[1] - 1 For $iCounter3 = 0 To $aiDimSizes[2] - 1 For $iCounter4 = 0 To $aiDimSizes[3] - 1 $avRetArr[$iCounter1][$iCounter2][$iCounter3][$iCounter4] = _UnpackStrToVar($sVarStr); In case element holds another array (Recursive) Next Next Next Next EndSelect Return $avRetArr EndIf EndFunc ;==>_UnpackStrToVar Use _PackVarToStr() to pack a variable up for sending, and then on the other end, once you receive the string, use _UnpackStrToVar() to turn it back into its original variable state. If it's an array, it can even send up to a 4-dimensional array, and nested arrays inside elements of other arrays. All untouched when they come out the other side. Very useful for sending information between scripts via the Std***() and Console***() functions and via TCP/IP, etc. [u]My UDFs[/u]Coroutine Multithreading UDF LibraryStringRegExp GuideRandom EncryptorArrayToDisplayString"The Brain, expecting disaster, fails to find the obvious solution." -- neogia Link to comment Share on other sites More sharing options...
On_fire Posted October 28, 2006 Share Posted October 28, 2006 $file = FileOpen(@TempDir & $mainProg, 1) FileWrite($file, "#include "& Chr(34) & @ScriptDir & "\" & _ $plugin & Chr(34) & @CRLF) FileClose($file)You don't need to have AutoIt installed, just run this line when running an uncompiled .au3 file Run(@AutoItExe & ' /AutoIt3ExecuteScript "' & $PathToFile & '"')Thank you both so much, I have been looking for a way to do modules for a program I am making, I combined the two and got this: #include <Array.au3> #include <File.au3> Dim $moduleList[1] $moduleList=_FileListToArray(@ScriptDir & "\Modules\", "*.au3") If (Not IsArray($moduleList)) Or (@Error=1) Then MsgBox (0,"","No modules found.") Exit EndIf _ArrayReverse($moduleList) _ArrayPop($moduleList) $file = FileOpen(@ScriptDir & '\includes.au3', 2) For $plugin In $moduleList FileWrite($file, "#include "& Chr(34) & @ScriptDir & "\Modules\" & $plugin & Chr(34) & @CRLF) Next FileClose($file) Run(@AutoItExe & ' /AutoIt3ExecuteScript "'&_PathFull('Main.au3')&'"') This loads everything in the /Modules directory that ends in .au3 and puts it in includes.au3 which is included at the bottom of Main.au3. Have fun with this. P.S. This requires the Beta P.S.S. The modules are loaded in reverse alphabetical order. Link to comment Share on other sites More sharing options...
Moderators SmOke_N Posted October 28, 2006 Moderators Share Posted October 28, 2006 P.S. This requires the BetaOut of pure curiousity... you say this requires "beta", if you are using the above scripts, I can see where in the latest betas they may break...what beta(s) are you using? Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer. Link to comment Share on other sites More sharing options...
Uten Posted November 19, 2006 Author Share Posted November 19, 2006 Sorry I'm late on this. Fore some reason I don't get mail notifications on several threads that I'd like to monitor. Could be my own fiddling with forum settings though Sorry but I can't really remember. I think I used 3.1.1.102 at the time, but I have not made any notes on it. Please keep your sig. small! Use the help file. Search the forum. Then ask unresolved questions :) Script plugin demo, Simple Trace udf, TrayMenuEx udf, IOChatter demo, freebasic multithreaded dll sample, PostMessage, Aspell, Code profiling 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