SRAutomater Posted November 8, 2007 Share Posted November 8, 2007 Hi, What I want to do is define the hotkeys for my program within an ini file, so the ini file would look something like: [functions] function1=alt+control+shift+a function2=ctrl+b A problem arises if the ini file defines a function that does not exist within the script. In this case the script stops with "Unknown function name.: " I have tried AutoItSetOption("RunErrorsFatal", 0), but this does not help. Ideally one would fill an array with all of the function names within my compiled script and then check that function name before setting it with HotKeySet(...). I believe this ability is called reflection. I guess I could read in the script.au3 file and write all of the function names to the ini file before hand, but I am looking for something a little more elegant and robust. Anyone have some ideas? Thank you. Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 8, 2007 Share Posted November 8, 2007 (edited) make an array with all the function names and say something like #include <array.au3> $AllFuncs = _ArrayCreate( 'Play', 'Pause', 'Stop', 'Exit', 'Test' ) ;An array containing all your function names $FuncFromINI = 'Play' ;the func the user is trying to call from the INI $OK = 0 ; this var is to say if the func was found or not If IsArray($AllFuncs) Then For $i=0 to Ubound($allFuncs)-1 step 1 If $FuncFromINI = $AllFuncs[$i] Then $Ok = 1 Next If $ok = 1 Then MsgBox(64,'','Function is in your script') Else MsgBox(64,'','Function is not in your script') Endif Endif Tested and works.... Edited November 8, 2007 by DBak [center][/center] Link to comment Share on other sites More sharing options...
SRAutomater Posted November 8, 2007 Author Share Posted November 8, 2007 Yes, that method would work, but we will be adding and removing functions rather regularly. I do not want to have to modify a list somewhere in the source... just have the code detect it automatically. Func findFunctions() If Not @Compiled Then $file = FileOpen(@ScriptFullPath, 0) While 1 $line = FileReadLine($file) If @error = -1 Then ExitLoop If StringLower(StringLeft($line, 5)) = "func " Then $function_name = StringSplit(StringTrimLeft($line, 5), "(") IniWrite($config_file, "functions", $function_name[1], "") EndIf Wend EndIf EndFuncoÝ÷ Ù8b³¥)ºVzØ^xW°ØZ+-¡úh²ÈçîËb¢{-«hçj-쨻ûazë®f¤zƦËZæ§vjø²Ø^~éܶ*'©¶§¶¬r¸©·¥×«)Úµì!zx¶¸²Ú,zÛajØh¶G²!Ê.ÙÉ·¯+h~)Ýéܶ*'±©Ý¶§Â¸zØZ¶X¬µ¶Ú-ëh¦íë®*m²«qâyªíì"Ú0³¥jZíçâëa¢è!jwHÂ÷öÖÞi¹^¶¨v'òÑÚ±©ò¢w°®+mzv¬zWæ¡ØÊ)à±Êâ¦Ûyú+z«¨µéÚ Tested and works.... Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 8, 2007 Share Posted November 8, 2007 Ok let me write something else that can modify itself... give me at least 20 or 30 mins [center][/center] Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 8, 2007 Share Posted November 8, 2007 Ok i'm almost done adding final touches... [center][/center] Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 8, 2007 Share Posted November 8, 2007 Ok include this into your script i left a few comments. Only works if the script ISN'T compiled!! #include <file.au3> #include <string.au3> #include <array.au3> If @Compiled = 0 then ;<======This will read every function it your script, but YOU Must have Func(space)Fucntion_Name( $YourScriptDir = @ScriptFullPath $Ini = "C:\Funcs.ini" ;<===Where to store the data at.... $Fhand = FileOpen( $YourScriptDir, 0 ) ;opens script in read mode MsgBox(64,'',_FileCountLines($yourscriptdir)) If _FileCountLines( $YourScriptDir ) > 1 and FileExists($YourScriptDir ) Then For $i = 1 to _FileCountLines( $YourScriptDir ) step 1 $YourScriptTxt = FileReadLine( $Fhand, $i ) ;Line Data, this line make take a while to complete.... IF StringinStr( $yourScriptTxt, 'Func' ) <> 0 Then $Name = _StringBetween( $YourScriptTxt, 'Func ', '(' ) IF IsArray($name) then IniWrite( $Ini, 'Function Names', $i, $Name[0] ) EndIf Next EndIf Endif ;<========End of reading fucntion names, should head your script.. (2.219 sec with 1256 lines) ;======Below reads to see if the Fucntion the user wants to call is valid========= $FuncFromINI = 'AutoPlay' ;<=============================INSERT The Func Name HERE $OK = 0 ; this var is to say if the func was found or not $AllFuncs = IniReadSection( $Ini, "Function Names" ) If IsArray($AllFuncs) Then For $i=0 to Ubound($allFuncs)-1 step 1 If $FuncFromINI = $AllFuncs[$i][1] Then $Ok = 1 Next If $ok = 1 Then MsgBox(64,'','Function is in your script') Else MsgBox(64,'','Function is not in your script') Endif Endif [center][/center] Link to comment Share on other sites More sharing options...
SRAutomater Posted November 9, 2007 Author Share Posted November 9, 2007 Thank you for all of your hard work on this problem DBak! I think you may have misunderstood though. Your new code essential does what I had posted earlier: Func findFunctions() If Not @Compiled Then $file = FileOpen(@ScriptFullPath, 0) While 1 $line = FileReadLine($file) If @error = -1 Then ExitLoop If StringLower(StringLeft($line, 5)) = "func " Then $function_name = StringSplit(StringTrimLeft($line, 5), "(") IniWrite($config_file, "functions", $function_name[1], "") EndIf Wend EndIf EndFuncoÝ÷ ÙhZ´×¶hÁ«-jGçîËb¢yb²×(¥yا~)Ýéܶ*'±©Ý¶§¦·©zwm«Z±©Ú®¶²uç%j¶í¢Ø^®éçx,r¸©µ«·~)^J²±Êâ¦Ö®Ýø¥{ .ÚÞiÛ®*mjíßwb¥Ø^~éܶ*'uç%j¶ÚÛazy¨v'ò±Êâ¦Ö®ÞÚuÖ§jºÚÉתڶ*'¡ö¥Ø^~éܶ*'©±8^欢r'yçm¡Ú-+"²Úç$jIèÂx(¡Ùb²Ú~éܶ*'©³Øh±è§¶¢'âì!Èfk&Þrëº^tzÞ¦ºé¡z·W¥éÜjz)zvW¢¼+ا)èê· &¡×¬^Õªizwl¶ayéÝ¡ûayø¥y©Ý^ÙêÚ±ë-çâä覷©zwZ)Þ¶ayø¥xÞyÛhr·µæzjhªò~)^!©£ºËg¢Û.趫ºyâ®*m~)^q©Ûz^çbj{b¦èºÛh¶¼«m «¨µéÚ Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 9, 2007 Share Posted November 9, 2007 read the help file there is more than two modes theres 0-Read 1-Append 2-? 8-Create File & Dir if it doesn't exist and so on [center][/center] Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 9, 2007 Share Posted November 9, 2007 I'm not sure what you want it too do, kind of confused... [center][/center] Link to comment Share on other sites More sharing options...
SRAutomater Posted November 9, 2007 Author Share Posted November 9, 2007 Only two of those modes allow you to write to a file. This is what I want to doread the help file there is more than two modes theres0-Read1-Append2-?8-Create File & Dir if it doesn't existand so on Link to comment Share on other sites More sharing options...
SRAutomater Posted November 9, 2007 Author Share Posted November 9, 2007 What I want myScript.au3 to do is find all of the functions contained within myScript.au3 and then modify the myScript.au3 source to include a statement like this: Dim $myScript_functions[12]="function1", "function2", etc... ... a self-modifying script. I'm not sure what you want it too do, kind of confused... Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 9, 2007 Share Posted November 9, 2007 What I want myScript.au3 to do is find all of the functions contained within myScript.au3 and then modify the myScript.au3 source to include a statement like this: Dim $myScript_functions[12]="function1", "function2", etc... ... a self-modifying script. um ok hmm give me a min to think... [center][/center] Link to comment Share on other sites More sharing options...
DirtDBaK Posted November 9, 2007 Share Posted November 9, 2007 Ok well heres your solution $AllFuncs = IniReadSection( $Ini, "Function Names" )oÝ÷ ÚØZ¶·vÆ¥Ø^~§t[§rv¦zȧ¶§jºÚÉ«¢+ØÀÌØí±±Õ¹ÍlÁulÁtíѽѰ½Õ¹9µÌ(ÀÌØí±±Õ¹ÍlÀÌØí¹Ñ¡ulÅtí%LÑ¡ÀÌØí¹Ñ Ù±Õ(íQ¡ÅÍн±Õµ¸¥ÌѼ¥¹¥Ñå½ÔݹÑÑ¡Ù±Õ¹À¥ÙÌå½ÔÑ¡ Modify as needed but it serves the purpose you want... [center][/center] Link to comment Share on other sites More sharing options...
SRAutomater Posted November 9, 2007 Author Share Posted November 9, 2007 I wish it did do what I want, but its not that simple. I am reading these keys and values from the ini file so I can set hotkeys in my program. I want the user to modify the ini file instead of the source file. The ini 'key' = function name and the 'value' = hotkey string. The problem is that if the user inadvertently changes the function name, and the function is not in the script file, then HotKeySet($function_name, $hotkey_combination) will fail and the script will terminate immediately. This is not good. I had originally hoped to trapped this error and continue executing the script, but I do not know how to do this. My workaround was to create a list of KNOWN good function names and compare those with the ones in the ini file. If the function name in the ini file does not match one in my list, then I will not try to set its hotkey. The script will be compiled, so I can not read through @ScriptFullPath to find the function names. The function names need to compiled into the script. I do not want to change the array of good function names by hand, so that is the reason I need to write the self modifying code. Does this make sense? Ok well heres your solution $AllFuncs = IniReadSection( $Ini, "Function Names" )oÝ÷ ÚØZ¶·vÆ¥Ø^~§t[§rv¦zȧ¶§jºÚÉ«¢+ØÀÌØí±±Õ¹ÍlÁulÁtíѽѰ½Õ¹9µÌ(ÀÌØí±±Õ¹ÍlÀÌØí¹Ñ¡ulÅtí%LÑ¡ÀÌØí¹Ñ Ù±Õ(íQ¡ÅÍн±Õµ¸¥ÌѼ¥¹¥Ñå½ÔݹÑÑ¡Ù±Õ¹À¥ÙÌå½ÔÑ¡ Modify as needed but it serves the purpose you want... Link to comment Share on other sites More sharing options...
therks Posted November 9, 2007 Share Posted November 9, 2007 (edited) Would be nice if we had an IsDeclared for function names, eh? Would you be satisfied with running a separate script everytime you compile to create the list of good functions? Cus that should be fairly simple. Try running this function on your script file. Func _FunctionListHeaderWrite($sFile) If Not FileExists($sFile) Then Return SetError(1, 0, 0) Local $sFileContents = FileRead($sFile, FileGetSize($sFile)) If @error Then Return SetError(2, 0, 0) Local $aFunctionList = StringRegExp($sFileContents, '(?m)(?i)^Func (\w[\w0-9]*)\(', 3) If Not @error Then Local $iFuncCount = UBound($aFunctionList) Local $sHeaderCode = 'Global $aFunctionList[' & $iFuncCount & '] = [ ' For $i = 0 To $iFuncCount - 1 $sHeaderCode &= '"' & $aFunctionList[$i] & '", ' Next $sHeaderCode = '#Region FunctionList' & @CRLF & StringTrimRight($sHeaderCode, 2) & ' ]' & @CRLF & '#EndRegion FunctionList' Local $sRESearch = '(?m)(?i)(?s)^#Region FunctionList.*#EndRegion FunctionList' If StringRegExp($sFileContents, $sRESearch) Then $sFileContents = StringRegExpReplace($sFileContents, $sRESearch, $sHeaderCode) Else $sFileContents = $sHeaderCode & @CRLF & $sFileContents EndIf $hFileWrite = FileOpen($sFile, 2) If $hFileWrite <> -1 Then FileWrite($hFileWrite, $sFileContents) FileClose($hFileWrite) Return True Else Return SetError(3, 0, 0) EndIf Else Return SetError(4, 0, 0) EndIf EndFuncoÝ÷ ØGb´¬¶Úªâ+aÌ"X§±êíiÈnJr^jÛazÚ)¡ü¨º»®*m)¶¢YhÂ)àjëh×6#Region FunctionList Global $aFunctionList[5] = [ "_VarDumpByRef", "_VarDump", "_VarCompare", "_VarDumpArray", "_VarDumpStruct" ] #EndRegion FunctionList Or, if that chunk of code already exists, it will replace it (so you won't end up with extra array declarations). Edited November 9, 2007 by Saunders My AutoIt Stuff | My Github Link to comment Share on other sites More sharing options...
SRAutomater Posted January 18, 2008 Author Share Posted January 18, 2008 Thank you so much Saunders! This code is exceptionally robust and most importantly, FAST! I really didn't like the idea of using a separate script so I just stuck it into my script and ran it.... turns out the StringRegExpReplace was matching everything in between the first #region down to the #endregion in _FunctionListHeaderWrite. This was solved easily enough by breaking up that string with ampersands. Now it works perfectly. $sHeaderCode = '#Region ' & 'FunctionList' & @CRLF & StringTrimRight($sHeaderCode, 2) & ' ]' & @CRLF & '#EndRegion ' & 'FunctionList' Local $sRESearch = '(?m)(?i)(?s)^#Region ' & 'FunctionList.*#EndRegion ' & 'FunctionList' Thanks again! 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