vagabond719 Posted November 4, 2016 Share Posted November 4, 2016 At work I use a ticketing system called ServiceNow. I can run scripts using this example $oIE.document.parentWindow.execScript. I am able to create a JS variable using the execScript method. Though it does not return a value. I can see the variable I need from the console. I have seen in the past $oIE.document.parentWindow.eval was used but this does not seem to work with IE 11. Is there anyway to pull a JS variable into Autoit? Currently I am writing the results of one of the ServiceNow queries to an empty text box but I am hoping for another option. Link to comment Share on other sites More sharing options...
Juvigy Posted November 4, 2016 Share Posted November 4, 2016 (edited) You create it , but do you assign a value to it? If it is 'empty' it is normal not to return any value! Edited November 4, 2016 by Juvigy spell check Link to comment Share on other sites More sharing options...
Gianni Posted November 4, 2016 Share Posted November 4, 2016 I've done some tests (a bit botched) about this matter in this my topic and found (in my opinion) some interesting points: 1) you shouldn't use the execscript method since is no longer supported, use eval instead(source is here: https://msdn.microsoft.com/en-us/library/ms536420(v=vs.85).aspx 2) to access javascript variables from AutoIt script you should: create a reference to the Javascript Global Object within your HTML page using this code in the <head> session: (source is here: http://stackoverflow.com/questions/9642491/getting-a-reference-to-the-global-object-in-an-unknown-environment-in-strict-mod (see first answer)) <script type="text/javascript"> var JSglobal = (1,eval)("this"); </script> 3) from the AutoIt script create an Object Handle to the above reference using this code: Global $ohJS = $oIE.document.parentwindow.JSglobal ; $ohJS is a reference to the javascript Global Obj 4) Use the $ohJS in your AutoIt script to read a javascript variable from the HTML page in a way like this: $ohJS.myjsvariable you can also use $ohJS to call javascript methods and get mthod's result back in an AutoIt variable using the eval method of the global object Local $result = $ohJS.eval('parseInt( 10000 ).toLocaleString();') MsgBox(0, "Debug", $result) see my tests in post #9 and #12 of this topic p.s. Sorry if i'm not such clear.... but it works Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
junkew Posted November 4, 2016 Share Posted November 4, 2016 (edited) As Servicenow is a webbased GUI why not read the element values itself? Why is javascript needed? 1. use IE.AU3 to get normal findelement and the related value 2. use Simplespy and uiwrappers/cuiautomation (See examples section) 3. Call somehow the javascript as Chimp gives examples on 4. use webdriver https://www.mkyong.com/selenium/how-to-execute-javascript-in-selenium-webdriver/ 1 is easiest and 4 is hardest edit: an additional one can just be to do a sendkeys to the addressbar with a value: javascript: alert(document.body.innerHTML); Edited November 4, 2016 by junkew FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
vagabond719 Posted November 7, 2016 Author Share Posted November 7, 2016 Chimp, When I use _IEAttach I am not able to call any value like this $oIE.document.parentwindow.JSglobal. I can via the browser console. Are you using _IEAttach and what browser are you using? Link to comment Share on other sites More sharing options...
vagabond719 Posted November 8, 2016 Author Share Posted November 8, 2016 I see Chimp you are using ObjCreate("Shell.Explorer.2") vs ObjCreate("InternetExplorer.Application") in the IE.au3. I was able to take one of your examples and it works on my PC. Do you know if it is possible to attach to an open IE window with this type of object? I am trying to research it now. Link to comment Share on other sites More sharing options...
vagabond719 Posted November 8, 2016 Author Share Posted November 8, 2016 Junkew, I was reading over your suggestions these look great from an automation stand point. My issue is I need to run glide queries in ServiceNow. I can run the queries via JS but I am using execScript because eval does not work. So I am stuck saving the results of the JS to an element so I can bring it into AutoIt. Otherwise I do go directly for the element. Link to comment Share on other sites More sharing options...
junkew Posted November 9, 2016 Share Posted November 9, 2016 (edited) If you see it in your html of IE by viewing source you should be able to get it out. some tricks are nicer then others. You can append the html with a 1 pix textbox with body.append and fill that with js and read it with ie.au3 See www.autoitscript.com/forum/topic/177711-wait-until-part-of-web-page-loads/ Edited November 9, 2016 by junkew FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
vagabond719 Posted November 9, 2016 Author Share Posted November 9, 2016 Here is an example of a Glide Query. As you can see it has nothing to do with an element on the page. This particular query is to pull the requestor of the parent ticket email address. var MainAppWin = "undefined" != typeof g_form ? window : document.getElementById("gsft_main").contentWindow, gr = new MainAppWin.GlideRecord("x_human_access_request"); gr.addQuery("sys_id", MainAppWin.g_form.getValue("parent")), gr.query(function(e) { if (e.next()) { var n = new MainAppWin.GlideRecord("sys_user"); n.addQuery("sys_id", e.getValue("opened_by")), n.query(function(e) { e.next() && MainAppWin.g_form.setValue("close_notes", e.email) }) } }); Link to comment Share on other sites More sharing options...
Gianni Posted November 10, 2016 Share Posted November 10, 2016 On 8/11/2016 at 5:32 PM, vagabond719 said: I see Chimp you are using ObjCreate("Shell.Explorer.2") vs ObjCreate("InternetExplorer.Application") in the IE.au3. I was able to take one of your examples and it works on my PC. Do you know if it is possible to attach to an open IE window with this type of object? I am trying to research it now. .... I do not know why this method works on the Browser Control but it doesn't in the Internet Explorer Window. following scripts show the issue, First script uses the Browser Control and will create the reference to the Javascript global obj in AutoIt through this reference we can access javascript variables and more... Second script uses the Internet Explorer Application instead and will fail on the attempt to reference to the Javascript global obj. I'm wondering why this happens and if there is a solution? if someone knows why, I would be also glad to know First script uses the Browser Control and successfully creates the Javascript global object variable expandcollapse popup#include <ie.au3> Local $hGUIMain = GUICreate("Browser", @DesktopWidth / 2, @DesktopHeight / 2) GUISetState() ;Show GUI ; We prepare the Browser Control as our test subject Global $oIE = ObjCreate("Shell.Explorer.2") $hIE = GUICtrlCreateObj($oIE, 0, 0, @DesktopWidth / 2, @DesktopHeight / 2) ; <- embedd $oIE in the AutoIt GUI $oIE.navigate('www.google.com') Sleep(3000) Local $oDocument Do Sleep(250) $oDocument = $oIE.document Until IsObj($oDocument) ; get reference to the <head> tag Local $oHead = _IETagNameGetCollection($oIE, "head", 0) ; we inject in the html page, within the <head> session, some <a> elements containing our javascript code ; this javascript will create the variable JSgloba containing a reference to the javascript globa object ; (and will also fire a popup just to show that this snippet was executed) Local $sJSCode_0 = '<a id="mylink"; href=' & "'javascript:var JSglobal = (1,eval)(" & '"this"); alert("Debug: javascript executed"' & "); void(0);'>" ; this javascript will fire a popup to show that the JSglobal obj variable exists ; we know that it exist because we use a method from this variable within the alert() Local $sJSCode_1 = '<a id="checkvar"; href=' & "'javascript: alert(" & '"Debug: Javascript engine build version is " + JSglobal.ScriptEngineBuildVersion()' & "); void(0);'>" ; --- THE INSERTION ORDER IS IMPORTANT. DO NOT CHANGE ORDER _IEDocInsertHTML($oHead, $sJSCode_1, "afterbegin") _IEDocInsertHTML($oHead, $sJSCode_0, "afterbegin") ; ---------------------------------------------------------- Local $oLink ; get a reference to proper <a> elements $oLink = _IEGetObjById($oIE, "mylink") ; First <a> Javascript to create the variable JSglobal ; and execute it's javascript $oLink.click() ; execute javascript_0 $oLink = _IEGetObjById($oIE, "checkvar") ; Second <a> Javascript for debug purpose $oLink.click() ; execute javascript_1 ; this shoul get reference to the JSglobal obj variable from javascript to AutoIt ; THIS WORKS IN AN EMBEDDED BROWSER CONTROL BUT DOES NOT WORKS IN AN INTERNET EXPLORER BROWSER WINDOW Global $ohJS = $oIE.document.parentwindow.JSglobal ; $ohJS is a reference to the javascript Global Obj MsgBox(0, "Debug from AutoIt", "Javascript global obj created in AutoIt. " & IsObj($ohJS)) Second script will fail on the attempt to reference to the Javascript global obj expandcollapse popup#include <ie.au3> Local $oIE = _IECreate("www.google.com") Local $oDocument Do Sleep(250) $oDocument = $oIE.document Until IsObj($oDocument) ; get reference to the <head> tag Local $oHead = _IETagNameGetCollection($oIE, "head", 0) ; we inject in the html page, within the <head> session, some <a> elements containing our javascript code ; this javascript will create the variable JSgloba containing a reference to the javascript globa object ; (and will also fire a popup just to show that this snippet was executed) Local $sJSCode_0 = '<a id="mylink"; href=' & "'javascript:var JSglobal = (1,eval)(" & '"this"); alert("Debug: javascript executed"' & "); void(0);'>" ; this javascript will fire a popup to show that the JSglobal obj variable exists ; we know that it exist because we use a method from this variable within the alert() Local $sJSCode_1 = '<a id="checkvar"; href=' & "'javascript: alert(" & '"Debug: Javascript engine build version is " + JSglobal.ScriptEngineBuildVersion()' & "); void(0);'>" ; --- THE INSERTION ORDER IS IMPORTANT. DO NOT CHANGE ORDER _IEDocInsertHTML($oHead, $sJSCode_1, "afterbegin") _IEDocInsertHTML($oHead, $sJSCode_0, "afterbegin") ; ---------------------------------------------------------- Local $oLink ; get a reference to proper <a> elements $oLink = _IEGetObjById($oIE, "mylink") ; First <a> Javascript to create the variable JSglobal ; and execute it's javascript $oLink.click() ; execute javascript_0 $oLink = _IEGetObjById($oIE, "checkvar") ; Second <a> Javascript for debug purpose $oLink.click() ; execute javascript_1 ; this shoul get reference to the JSglobal obj variable from javascript to AutoIt ; THIS WORKS IN AN EMBEDDED BROWSER CONTROL BUT DOES NOT WORKS IN AN INTERNET EXPLORER BROWSER WINDOW Global $ohJS = $oIE.document.parentwindow.JSglobal ; $ohJS is a reference to the javascript Global Obj MsgBox(0, "Debug from AutoIt", "Javascript global obj created in AutoIt. " & IsObj($ohJS)) Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
vagabond719 Posted November 10, 2016 Author Share Posted November 10, 2016 Chimp, Do you know of a way to bind to an open IE window after creating the ObjCreate("Shell.Explorer.2")? Link to comment Share on other sites More sharing options...
junkew Posted November 10, 2016 Share Posted November 10, 2016 Here I think you have a workaround http://stackoverflow.com/questions/26021813/ie-com-automation-how-to-get-the-return-value-of-window-execscript-in-powersh FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
genius257 Posted November 11, 2016 Share Posted November 11, 2016 i found a workaround, that works for me: #include <IE.au3> Global $oIE = _IECreate("about:blank") Global $eval = 0 $oIE.Document.parentWindow.execScript("document.body.oAutoIt = eval;") $eval = Execute("$oIE.Document.body.oAutoIt") If IsObj($eval) Then MsgBox(0, "eval", $eval('typeof "str"'));execute js and get return $eval("alert('test');") EndIf hope it's useful to someone ss26, mLipok and Gianni 3 My highlighted topics: AutoIt Package Manager, AutoItObject Pure AutoIt, AutoIt extension for Visual Studio Code Github: AutoIt HTTP Server, AutoIt HTML Parser Link to comment Share on other sites More sharing options...
Gianni Posted November 13, 2016 Share Posted November 13, 2016 On 11/11/2016 at 7:06 PM, genius257 said: i found a workaround, that works for me: Nice Shot @genius257! you should anyway try to achieve the same result without the execScript method (seems that execScript is going to be dismissed. see here: https://msdn.microsoft.com/en-us/library/ms536420(v=vs.85).aspx ). I tryed to achieve the same result without the execScript method in post #10, but I failed miserably.... Hope you will come out also with something that doesn't relies on the javascript ecexScript method.... p.s. also, why you used the AutoIt Execute function?, $eval = Execute("$oIE.Document.body.oAutoIt") seems that it works also directly without the Execute, like this $eval = $oIE.Document.body.oAutoIt Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
genius257 Posted November 13, 2016 Share Posted November 13, 2016 Thanks @Chimp 10 hours ago, Chimp said: you should anyway try to achieve the same result without the execScript method (seems that execScript is going to be dismissed. see here: https://msdn.microsoft.com/en-us/library/ms536420(v=vs.85).aspx ). I tryed to achieve the same result without the execScript method in post #10, but I failed miserably.... Hope you will come out also with something that doesn't relies on the javascript ecexScript method.... Well i am aware of using execScript does present problems for the future. But they promise eval, in which case, the issue solves itself, no? (also, they say it's staring from IE 11, and that's what I'm using, yet no eval :/ ) 10 hours ago, Chimp said: also, why you used the AutoIt Execute function? I use Execute, so in case of error, the script won't crash. It's just my quick way to avoid crashes, without catching the errors with something like ObjEvent("AutoIt.Error",...) My highlighted topics: AutoIt Package Manager, AutoItObject Pure AutoIt, AutoIt extension for Visual Studio Code Github: AutoIt HTTP Server, AutoIt HTML Parser Link to comment Share on other sites More sharing options...
Gianni Posted November 13, 2016 Share Posted November 13, 2016 7 hours ago, genius257 said: Well i am aware of using execScript does present problems for the future. But they promise eval, in which case, the issue solves itself, no? I think that is not exactly like that, execScript() is a method of the javascript window obj, while eval() is a method of the Javascript Global Object. each one belongs to a different object, and both are already present. (perhaps execScript is still there for back compatibility (at least for now...) Since execScript() is a method of the javascript window obj, you can easily get an handle to it, and you can as well easily call its methods. eval() is instead a method of the javascript global obj. In the remarks of the msdn documentation about the javascript Global Obj is stated this sentence: "The Global object is never used directly, and cannot be created using the new operator. It is created when the scripting engine is initialized, thus making its functions and constants available immediately." So, for what I understand, Global Object's methods can be called from within the javascript environment, but you can not create a reference from the outside. (or better, is not as immediate). To be able to get a reference to the Javascript Global Object, maybe some sort of workaround is to be found. Here is a question on StackOverflow about this matter with a plausible answer (see first answer) here and here are two points of an article written by the answerer. Using the information contained there, I'm been able to get a reference to the Javascript Global Obj only using the "Browser Control" (Shell.Explorer.2). (First script in above post#10) I've failed attempting to get the same reference within the Internet explorer browser (using "InternetExplorer.Application" or _iEcreate()) (second script in post#10) I've also seen by using the ObjName() function, that the Module name in which the object runs is: 1) When I get a reference to the Javascript Global Object from within the Browser control, the ObjName($oIE, $OBJ_MODULE), returns jscript9.dll 2) When I get a reference to the Javascript Global Object from the script provided by @genius257 in post#13, the ObjName($oIE, $OBJ_MODULE), returns OLEAUT32.dll Also, with that script you get a reference to the eval() function within javascript global obj and not to the Javascript global obj itself. 3) If I use the below script, that is a little variation to @genius's script, I get a reference to the whole Javascript Global Obj instead. I think is better a reference to the whole Obj instead of to its eval() function only. also, in this last case the ObjName($oIE, $OBJ_MODULE), returns mshtml.dll #include <IE.au3> Global $oIE = _IECreate("about:blank") Global $eval = 0 ; $oIE.Document.parentWindow.execScript("document.body.oAutoIt = eval;") ; this returns a reference to the eval() function only $oIE.Document.parentWindow.execScript('oAutoIt = (1,eval)("this");') ; this returns a reference to the javascript Global Object $oIE.Document.parentWindow.execScript('jsVariable = "Hello from Javascript";') ; this declares a javascript variable ; $eval = Execute("$oIE.Document.body.oAutoIt") $eval = $oIE.Document.parentwindow.oAutoIt If IsObj($eval) Then MsgBox(0, "ObjName", ObjName($eval, 5)) ; MsgBox(0, "eval", $eval('typeof "str"'));execute js and get return MsgBox(0, "eval", $eval.eval('typeof "str"')) ; $eval("alert('test');") $eval.eval('alert("test");') ; this is another method of the Javascript Global Object MsgBox(0, "JS engine Build Version", "Javascript engine build version is " & $eval.eval('oAutoIt.ScriptEngineBuildVersion();')) MsgBox(0, "value of a js variable", "Javascript variable value is " & @CRLF & @CRLF & $eval.jsVariable) EndIf anyway, what I think would be interesting, is to find a way to refer the Javascript Global Obj from within the Internet Explorer, without the use of the ExecScript() method. Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
genius257 Posted November 14, 2016 Share Posted November 14, 2016 Hi @Chimp thanks for the extensive reply ^^' I will look into your information , thank you. 1 hour ago, Chimp said: #include <IE.au3> Global $oIE = _IECreate("about:blank") Global $eval = 0 ; $oIE.Document.parentWindow.execScript("document.body.oAutoIt = eval;") ; this returns a reference to the eval() function only $oIE.Document.parentWindow.execScript('oAutoIt = (1,eval)("this");') ; this returns a reference to the javascript Global Object $oIE.Document.parentWindow.execScript('jsVariable = "Hello from Javascript";') ; this declares a javascript variable ; $eval = Execute("$oIE.Document.body.oAutoIt") $eval = $oIE.Document.parentwindow.oAutoIt If IsObj($eval) Then MsgBox(0, "ObjName", ObjName($eval, 5)) ; MsgBox(0, "eval", $eval('typeof "str"'));execute js and get return MsgBox(0, "eval", $eval.eval('typeof "str"')) ; $eval("alert('test');") $eval.eval('alert("test");') ; this is another method of the Javascript Global Object MsgBox(0, "JS engine Build Version", "Javascript engine build version is " & $eval.eval('oAutoIt.ScriptEngineBuildVersion();')) MsgBox(0, "value of a js variable", "Javascript variable value is " & @CRLF & @CRLF & $eval.jsVariable) EndIf I like your idea, but your code does not work with me. Also not using Execute, when defining the $eval in AutoIt, forces the script to crash, upon error. >Running:(3.3.14.2):C:\Program Files (x86)\AutoIt3\autoit3.exe "C:\Users\...\Desktop\script.au3" --> Press Ctrl+Alt+F5 to Restart or Ctrl+Break to Stop "C:\Users\...\Desktop\script.au3" (9) : ==> The requested action with this object has failed.: $eval = $oIE.Document.parentwindow.oAutoIt $eval = $oIE.Document.parentwindow^ ERROR ->02:01:20 AutoIT3.exe ended.rc:1 >Exit code: 1 Time: 2.245 My highlighted topics: AutoIt Package Manager, AutoItObject Pure AutoIt, AutoIt extension for Visual Studio Code Github: AutoIt HTTP Server, AutoIt HTML Parser Link to comment Share on other sites More sharing options...
Gianni Posted November 14, 2016 Share Posted November 14, 2016 13 hours ago, genius257 said: I like your idea, but your code does not work with me. Also not using Execute, when defining the $eval in AutoIt, forces the script to crash, upon error. indeed, it works on Internet Explorer 9, but it doesn't on Internet Explorer 11 (on IE11 it doesn't works even if you set compatibility mode down to IE9) ... nice effects of the IE upgrades.... Perhaps the issue is due to something listed here... https://msdn.microsoft.com/en-us/library/dn467846(v=vs.85).aspx Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... Link to comment Share on other sites More sharing options...
junkew Posted November 14, 2016 Share Posted November 14, 2016 msdn.microsoft.com/en-us/library/dn384057 Execscript not valid FAQ 31 How to click some elements, FAQ 40 Test automation with AutoIt, Multithreading CLR .NET Powershell CMDLets Link to comment Share on other sites More sharing options...
Gianni Posted November 15, 2016 Share Posted November 15, 2016 17 hours ago, junkew said: msdn.microsoft.com/en-us/library/dn384057 Execscript not valid Hi @junkew, No, the Execscript method is still working (at least for now), the problem here is that the Javascript Globa Object is no more referenceable from AutoIt, (or better, I am not aware of how), while it was in previous versions of IE instead. It seems that The Javascript Global Object has been armored and segregated within its own environment only. (If you know a way to reference the Javascript global object from AutoIt that I am not aware of, this is the answer I'm looking for.) Chimp small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt.... 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