eimhym Posted May 29, 2012 Share Posted May 29, 2012 Hi guys I'm new here, both in forum and using autoit. IMHO this really is awesome tool and great community too, clean documentation and abundant examples really helps. Thanks for your great effort and keep up!AutoIt doesn't support associative array which a bit let down, but hey, we got COM Extensions! You can get more info about COM here: yet another idea to implement it this thread is all about.; #FUNCTION# ================================================================== ; Name : _ComObj_init ; Description : Creates MS Windows Script control and deploy it as proxy for ; AutoIt COM object binding. ; Syntax : _ComObj_init([$VBScriptSupport = false]) ; Parameter : $VBScriptSupport ; By default JScript doesn't have alert() function, it is provided ; by browser's window object. ; We can emulate this using VBScript's MsgBox function, which is ; performance hog because we need another ScriptControl instance. ; Other advantage is to be able to execute other VBScript's methods ; within function via vb.Eval() method. ; This feature is disabled by default. ; ============================================================================= Func _ComObj_init ($VBScriptSupport = false) Local $_Script $_Script = ObjCreate("ScriptControl") $_Script.Language = "JScript" $_Script.Timeout = 60000 $_Script.AddCode("var $=this,arrays=[],vb;function set_vbscript($) {vb=$;vb.Language='VBScript';vb.AllowUI=true;}function alert(s){if(vb)vb.Eval('MsgBox(Unescape(""'+s+'""), 0, ""Autoit"")')}function get_proxy(){return $}function new_object($){$=new Function('return{'+$+'}')();$.set=function(k, v){$[k]=v};$.unset=function(k){delete $[k]};$.set_object=function(k,$){this.set(k,new_object($))};$.set_array=function(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];$.set(v.shift(),new_array.apply(this,v))};$.set_function=function(k,p,$){this.set(k,new_function(p,$))};return $}function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v}function array_get($,k){return $[k]}function array_set($,k,v){return $[k]=v}var new_function=(function(){function F(r) {return Function.apply(this,r)}F.prototype = Function.prototype;return function(p,$){p=p.split(/\s*,\s*/);p.push($);return new F(p)}})()") If $VBScriptSupport = true Then $_Script.Run("set_vbscript", ObjCreate("ScriptControl")) Return $_Script EndFunc ; =============================================================================This UDF only use Script Control methods to initialize the script engine, once loaded creation of object, function and array are done by the script itself. The script passed into AddCode method above is inlined to save space, the exploded version below:expandcollapse popup<html> <script language="javascript"> var $=this,arrays=[],vb; // VBScript support function set_vbscript($) { vb=$; vb.Language='VBScript'; vb.AllowUI=true; } // alert() emulation function _alert(s){if(vb)vb.Eval('MsgBox(Unescape("'+s+'"), 0, "Autoit")')} // Core functions function get_proxy(){return $} function new_object($){ $=new Function('return{'+$+'}')(); $.set=function(k, v){$[k]=v}; $.unset=function(k){delete $[k]}; $.set_object=function(k,$){this.set(k,new_object($))}; $.set_array=function(){ var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i]; $.set(v.shift(),new_array.apply(this,v)) }; $.set_function=function(k,p,$){this.set(k,new_function(p,$))}; return $ } function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v} function array_get($,k){return $[k]} function array_set($,k,v){return $[k]=v} function new_date(){return new Date()} var new_function=(function(){ function F(r) {return Function.apply(this,r)} F.prototype = Function.prototype; return function(p,$){p=p.split(/\s*,\s*/);p.push($);return new F(p)}} )(); function unit_test(){ var err; try { err = "function new_object test"; var obj = new_object("num:1234567890"); if (obj.num*1 !== 1234567890) throw err; obj.set_object("obj", "num:1234567890"); if (obj == obj.obj) throw err; // not the same object if (obj.num*1 !== obj.obj.num*1) throw err; err = "method object.set test"; obj.set("str", "a string"); if (typeof obj.str != "string" || obj.str != "a string") throw err; err = "method object.unset test"; obj.unset("str"); if (typeof obj.str != "undefined") throw err; err = "function new_array test"; var arr = new_array(1,2,3,4,5,6,7,8,9,0); obj.set_array("arr",1,2,3,4,5,6,7,8,9,0); for (var i in arr) if (arr[i] !== obj.arr[i]) throw err; err = "function new_function test"; var fn = new_function("a, b,c ,d", "(a+b)*c+d"); obj.set_function("fn", "a, b,c ,d", "(a+b)*c+d"); if (fn(1,2,3,"MB") !== obj.fn(1,2,3,"MB")) throw err; obj.set_function("is_same", "o", "return o==this"); // function's "this" reference test if (! obj.is_same(obj) ) throw err; err = "JScript alert support test"; if (window.ActiveXObject) { _alert("This should be swallowed"); set_vbscript( new ActiveXObject('ScriptControl') ); _alert("Hello from VB world!"); } else throw "please run this test with IE"; } catch (e) { alert(err + " failed: " + e); return } return true; } if ( unit_test() ) alert ("All tests passed."); </script> </html>As you can see these functions are merely wrapper for Javascript object creation, and COM nature provide AutoIt direct access toward its functions make the integration seamless. Example worth thousands words, so here we go:expandcollapse popup; ComObject; create and invoke COM object, properties, function and array: Local $_ComObj_proxy, $_com Local $obj, $complex_obj, $fn, $bucket, $array_to_string, $typeof, $i, $v ; Initialize COM Object proxy with VBScript support, to enable alert() feature. $_ComObj_proxy = _ComObj_init(true) ; $_com is now our gateway, providing methods: $_com = $_ComObj_proxy.Run("get_proxy") ; - new_object($json) ; Creates and return new COM object accessible from AutoIt. ; parameter: ; - JSON string to initialize new object ; or empty string to start with a basic one. ; Every objects created are equiped with set() and unset() method, so ; either start with a complex object or the basic one, we can always ; add or remove object's properties and methods. ; basic obj: $obj = $_com.new_object("") $obj.set("Version", @AutoItVersion) ; simple types $obj.set("randomVal", Random(10, 1000)) ; ; the complex one: $complex_obj = $_com.new_object( _ "num:123, str:'a string', arr:[1,2,3], " _ & "child:{msg:'Hello AutoIt World!'}, hail:function(){alert(this.child.msg + ' (' + this.AutoIt.Version + ')')}" _ ) $complex_obj.set("AutoIt", $obj) ; nesting our basic object as $complex_obj.AutoIt $complex_obj.hail() ; - new_function($parameters, $statements) ; Creates and return new owner-less function. ; We can later assign it into object via set() method. ; parameters: ; - A string of function parameter names, separated by comma. ; - A string contains all the function statements ; either this way: $fn = $_com.new_function("msg", "alert('You command me to say: ' + msg + '!')") $obj.set("blarp", $fn) $obj.blarp("AutoIt is Awesome") ; or use object's shortcut, both is the same $obj.set_function("calc", "size, h ,s", 'alert("For " + size + "MB disk image with " + h + " heads and " + s + " sector per track"+ escape("\r\n") + "You will need " + Math.ceil(size*Math.pow(2, 20)/h/s/512) + " cylinders to make it compatible with GRUB.")') $obj.calc(128, 16, 63); ; - new_array($value[, $value ...]) ; Creates and return new Variant array, ; We can later assign it into object via set() method. ; parameters: ; - list of comma delimited values. Value can be basic AutoIt variables (string or number) ; also can hold COM object or other JScript Array. ; NOTE: ; JScript Array is not compatible with AutoIt array, thus we can't ; access its items in AutoIt way. ; In fact JScript Array also not compatible with VBArray nor Variant Array, ; that because JScript Array is NOT actually an array. ; The good news is we have the full access to Array methods like push, pop, join, etc. ; while for Array item access these functions are provided: array_get and array_put (see below) $bucket = $_com.new_array(1, 2, 3, 4, "blue", "red", $obj) $obj.set("bucket", $bucket) ; object shortcut: $obj.set_array("box") ; empty array ; example to play with JScript Array $array_to_string = $_com.new_function("r", "var s='';for (var i=0;i<r.length;i++) s+=i==0?r[i]:', '+r[i];return s") MsgBox( 0, "Autoit", "Before: " & $array_to_string($bucket) ) $typeof = $_com.new_function("v", "return typeof v") For $i = 0 To $bucket.length - 1 $v = $_com.array_get($bucket, $i) ; array_get example $_com.array_set( $bucket, $i, $v & " is " & $typeof($v) ) ; array_put example If $typeof($v) = "number" Then $obj.box.push($v) EndIf Next MsgBox( 0, "Autoit", "After: " & $array_to_string($bucket) ) MsgBox( 0, "Autoit", "$obj.box: " & $array_to_string($obj.box) )And below is example to make AutoIt functions accessible from within JScript. For this purpose AutoItObject come in handy dandy, it cant be more easier. Thanks guys, AutoItObject - you want it expandcollapse popup; Exposing AutoIt functions with AutoItObject ; Render scene :P Run("notepad.exe") WinWaitActive("[CLASS:Notepad]") ; Prepare AutoItObject to be exposed _AutoItObject_Startup() Global $jsExposed = _AutoItObject_Create() _AutoItObject_AddMethod($jsExposed, "send", "_jsExposed_Send") _AutoItObject_AddMethod($jsExposed, "sleep", "_jsExposed_Sleep") Func _jsExposed_Send($oSelf, $keys) #forceref $oSelf Send($keys) EndFunc Func _jsExposed_Sleep($oSelf, $delay) #forceref $oSelf Sleep($delay) EndFunc ; Send AutoItObject into JScript world $obj.set("AutoIt", $jsExposed) $obj.set_function("play", "", "var key,$=this;" _ & "function log (s) { $.AutoIt.send(s) }" _ & "function sleep (c) { $.AutoIt.sleep(c) }" _ & "log('JScript object\'s member:{ENTER}');" _ & "log('------------------------{ENTER}');" _ & "sleep(700);" _ & "try {" _ & "for (key in $) {" _ & "if (typeof $[key] != 'undefined')" _ & "log( key + ' => ' + (typeof $[key]) + '{ENTER}');" _ & "log( '>>> ' + $[key] + '{ENTER}');" _ & "}" _ & "} catch(e) { alert(e) };" _ & "sleep(700);" _ & "log('{ENTER}{ENTER}5 secs to autodestruct ...{ENTER}');" _ & "sleep(5000);" _ ) $obj.play() ; Action ! ; clean up Send("!f") Send("x") WinWaitActive("Notepad") Send("n") WinWaitClose("[CLASS:Notepad]") $jsExposed = 0Thats it folks, have fun Tested with:+ AutoIt: v3.3.8.0 (feedback needed)+ AutoItObject: 1.2.8.2 (feedback needed)+ OS: XP SP3 (feedback needed)ComObject.zip Link to comment Share on other sites More sharing options...
eimhym Posted May 30, 2012 Author Share Posted May 30, 2012 First um ... I'm sorry, I don't know how to edit the first post yet anyone can help?So the update posted here:You now have Javascript Framework power within AutoIt! For example Array is now have each() method, no longger have to do For ... Next anymore Note: Only server-side framework is supported. MooTools is tested and work fine, please send your test result for other framewok whenever you can, thanksUpdateComObject is now isolated in UDF, new functions are: ComObject_Init ComObject_LoadFile ComObject_LoadHttpModifed core functions to support Javascript FrameworkFramework/Script can be loaded either from local file or web serverTest script now named ComObject.test.au3Tested Framework:MooToos v1.4.5ComObject_0001.zip Link to comment Share on other sites More sharing options...
eimhym Posted May 31, 2012 Author Share Posted May 31, 2012 Update:Now become JScriptObject, for: 1.) Now tightly coupled with AutoItObject. Include JScriptObject.au3 will automatically include AutoItObject (http://autoitobject.origo.ethz.ch/) 2.) More represents its nature. AutoItObject, which also a (customized) COM object specially crafted for AutoIt use. JScriptObject is plain JScript's object not (yet) hampered in anyway. Still, JScriptObject is accessible from AutoIt thanks to COM support.alert() is now emulated using AutoIt's MsgBox(). VBScript support no longer required but still an option if someone need to invoke VBS code.array_set() and array_get() replaced with Array.prototype.set() and get(). unset() introduced to remove an Array element (see example)Introduce _JScriptObject_AddMethod() which wrap _AutoItObject_AddMethod(). You can now easily assign AutoIt function as JScriptObject method .No need to create new AutoItObject (see example)To Do:Find a way (or ask AutoItObject team) to make AutoItObject can inherit from JScript's object. Any attempt resulting fatal error so faror even better: mock JScript object directly. For now AutoIt function call within JScript object has to take quite long route: JScript wrapper --> AutoItObject --> AutoIt function. This means serious debugging JScript's inner work, which, devotion required :duh:Not much, but as a proof-of-concept now JScriptObject have a pretty much clearer goal JScriptObject.zip Link to comment Share on other sites More sharing options...
eimhym Posted May 31, 2012 Author Share Posted May 31, 2012 Yesss! edit post button popping out of thin air LOL Link to comment Share on other sites More sharing options...
biase Posted October 18, 2012 Share Posted October 18, 2012 After played with your code for a while and the result is you can include a JS file.Maybe it's not interesting much but may be you or the others comes with new ideas.$fso = ObjCreate('Scripting.FileSystemObject') $jso = ObjCreate("ScriptControl") $jso.Language = "JScript" $jso.AddCode($fso.OpenTextFile("include.js", 1).ReadAll()) $jso.Run("set_vbscript", ObjCreate("ScriptControl")) $jsn = $jso.Run("get_proxy")and the include.jsvar $=this,arrays=[],vb;function set_vbscript($) {vb=$;vb.Language='VBScript';vb.AllowUI=true;}function alert(s){if(vb)vb.Eval('MsgBox(Unescape(""'+s+'""), 0, ""Autoit"")')}function get_proxy(){return $}function new_object($){$=new Function('return{'+$+'}')();$.set=function(k, v){$[k]=v};$.unset=function(k){delete $[k]};$.set_object=function(k,$){this.set(k,new_object($))};$.set_array=function(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];$.set(v.shift(),new_array.apply(this,v))};$.set_function=function(k,p,$){this.set(k,new_function(p,$))};return $}function new_array(){var v=[];for(var i=0;i<arguments.length;i++)v[i]=arguments[i];return v}function array_get($,k){return $[k]}function array_set($,k,v){return $[k]=v}var new_function=(function(){function F(r) {return Function.apply(this,r)}F.prototype = Function.prototype;return function(p,$){p=p.split(/\s*,\s*/);p.push($);return new F(p)}})()Not just that, you also can use other JScript codes inside it or you can use in other JS file and include it. 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