Powershell: using jQuery through InternetExplorer.Application

I followed in this article explaining how to animate an Internet Explorer COM object using jQuery. Although the author used Python, I want to do something similar in Powershell.

I now have this code:

function addJQuery ($browser) { $url="https://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js" $document = $browser.document $window = $document.parentWindow $head = @($document.getElementsByTagName("head"))[0] $script = $document.createElement("script") $script.type = "text/javascript" $script.src = $url $head.appendChild($script) while (!$window.jQuery) { sleep -milliseconds 100 } return $window.jQuery } $ie = New-Object -comobject InternetExplorer.Application $ie.visible = $true $ie.Navigate("https://some.site.com") while ($ie.busy) {start-sleep -milliseconds 500} $j = addJQuery $ie 

With Fiddler and through the document.scripts collection, I checked that the file is loading. However, the script sleeps forever, and when I try to print $ window.jQuery it doesn't print anything in the ISE Powershell console.

The script, however, is loaded correctly, since jQuery-Functions can be called from the browser console or through execScript ().

The problem seems to be that the DOM view, accessible through $ ie.document, is not updated when DOM changes are made using JavaScript. But shouldn't the Internet Explorer COM object behave the same in Powershell as it does in Python?

+4
source share
5 answers

Despite the fact that I also could not figure out how to directly work with JQuery as an object, below is as close as I could use Posh (I had to end the first line here on one line to make code formatting work):

 function addJQuery ($browser) { #helper function to highlight text $func=@ " function SelectText(element) { var text = document.getElementById(element); var range = document.body.createTextRange(); range.moveToElementText(text); range.select(); }"@ #needs to be at the beginning of the next line $url='http://code.jquery.com/jquery-1.4.2.min.js' $document = $browser.document $window = $document.parentWindow $head = @($document.getElementsByTagName("head"))[0] $script = $document.createElement('script') $script.type = 'text/javascript' $script.src = $url $head.appendChild($script) | Out-Null #inject helper function $script = $document.createElement('script') $script.type = 'text/javascript' $script.text = $func $head.appendChild($script) | Out-Null}#end function $ie = new-object -com internetexplorer.application $ie.visible = $true $ie.navigate2("http://www.example.com") # Wait for page load while($ie.busy) {start-sleep 1} # Inject jQuery addJQuery $ie #Test whether JQuery is usable $code1=@ " `$('a').hide(); "@ $code2=@ " var str=`$('p:first').text();`$('#myResult').html(str); "@ #add addtional div to store results $div="<div id='myResult'>" $ie.Document.body.innerHTML += $div #hide anchor tag $ie.document.parentWindow.execScript("$code1","javascript") #change innerhtml of div $ie.document.parentWindow.execScript("$code2","javascript") #retrieve the value $result = $ie.document.getElementById("myResult") $result.innerHtml #call SelectText function $ie.document.parentWindow.execScript("SelectText('myResult')","javascript") 
+1
source

I would like to read this last year. I also tried to integrate or "inject" jQuery into the Windows Scripting host environment. Also tried Powershell. No one worked. However, I managed to use this "InternetExplorer.Application" object with IE7, IE8, and now IE9.

 try{ var ie = new ActiveXObject("InternetExplorer.Application"); ie.navigate(url); ie.visible = false; ie.left=800; ie.top=0; ie.height=600; ie.width=900; //use this with ie.visible = true; do{} while (ie.busy); } catch (e){ console.log("Exception thrown: "+e) } finally { IE_waitLoad(ie); var webpage=ie.document.body.innerHTML ; $("#cache").append($(webpage)); ie.quit(); } 

After that, jQuery is your friend. Yet again!!!

I found this nice wait function somewhere on the web:

 function IE_waitLoad(pIE) { var stat, dstart; stat = 0; while(true){ if(stat == 0) { if(!pIE.Busy){ if(pIE.Document.readyState == "complete") { dstart = new Date().getTime(); stat = 1; } } }else{ if(!pIE.Busy && pIE.Document.readyState == "complete") { if(new Date().getTime() >= dstart + 1000){ break; } }else{ stat = 0; } } sleep(1000) } } 

The navigation function has all of these optional parameters.

 // ie.navigate(url,0x1000); navOpenInNewWindow = 0x1, navNoHistory = 0x2, navNoReadFromCache = 0x4, navNoWriteToCache = 0x8, navAllowAutosearch = 0x10, navBrowserBar = 0x20, navHyperlink = 0x40, navEnforceRestricted = 0x80, navNewWindowsManaged = 0x0100, navUntrustedForDownload = 0x0200, navTrustedForActiveX = 0x0400, navOpenInNewTab = 0x0800, navOpenInBackgroundTab = 0x1000, navKeepWordWheelText = 0x2000, navVirtualTab = 0x4000 
+1
source

In your while expression (!$window.jQuery) always returns true because $window is a ComObject and COM objects are not like JavaScript objects, so even if window.jQuery exists in JavaScript, it will not automatically visible in the $window object in PowerShell.

I really couldn't find a workaround to make jQuery objects available in powershell, and I am also interested to know if there is a way to do this. See this and this question that I created on this.

But I decided this trick to run javascript / jquery on a web page and get some results from the page in PowerShell:

 # some web page with jQuery in it $url = "http://jquery.com/" # Use this function to run JavaScript on a web page. Your $jsCommand can # return a value which will be returned by this function unless $global # switch is specified in which case $jsCommand will be executed in global # scope and cannot return a value. If you received error 80020101 it means # you need to fix your JavaScript code. Function ExecJavaScript($ie, $jsCommand, [switch]$global) { if (!$global) { $jsCommand = "document.body.setAttribute('PSResult', (function(){$jsCommand})());" } $document = $ie.document $window = $document.parentWindow $window.execScript($jsCommand, 'javascript') | Out-Null if (!$global) { return $document.body.getAttribute('PSResult') } } Function CheckJQueryExists { $result = ExecJavaScript $ie 'return window.hasOwnProperty("$");' return ($result -eq $true) } $ie = New-Object -COM InternetExplorer.Application -Property @{ Navigate = $url Visible = $false } do { Start-Sleep -m 100 } while ( $ie.ReadyState -ne 4 ) $jQueryExists = CheckJQueryExists $ie echo "jQuery exists? $jQueryExists" # make a jQuery call ExecJavaScript $ie @' // this is JS code, remember to use semicolons var content = $('#home-content'); return content.text(); '@ # Quit and dispose IE COM $ie.Quit() [System.Runtime.Interopservices.Marshal]::ReleaseComObject($ie) | out-null Remove-Variable ie 
+1
source

For some reason, I needed to make the browser window visible to mine even for distant work - without it, the Navigate method was unbearably slow, and the $ ie.Busy property would never seem to return anything but True. You should not do this, but good.

 $ie.Visible = $true 

By checking the collection of $ ie.Document.Scripts, you can check if the jQuery file was loaded, but I could not get the reference to the work of $ ie.Document.parentWindow, which also means that I cannot seem to go to the jQuery property. This is a well-known property, but it does not seem to be populated with anything useful, as it is passed to PowerShell.

0
source

You can see the source code for Invoke-JQuery . I tried this and I was able to use jquery to manipulate the page, although I did not modify the script to add jquery.

0
source

All Articles