2010-10-30 3 views
4

Я последовал за this article, объясняя, как оживить COM-объект Internet Explorer с помощью jQuery. Хотя автор использовал Python, я хочу сделать что-то подобное в Powershell.Powershell: Использование jQuery через InternetExplorer.Application

Сейчас у меня есть этот код:

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 

С Скрипач и через коллекцию document.scripts я проверил, что файл будет загружен. Тем не менее, сценарий спит навсегда, и когда я пытаюсь вывести $ window.jQuery, он ничего не выводит на консоль PowerShell ISE.

Сценарий, тем не менее, правильно загружен, поскольку jQuery-Functions можно вызвать из консоли браузера или с помощью execScript().

Похоже, проблема заключается в том, что DOM-представление, доступное через документ $ ie.document, не обновляется, когда изменения DOM выполняются с помощью JavaScript. Но не должен ли COM-объект Internet Explorer вести себя таким же образом в Powershell, как в Python?

+0

Вы пробовали Watin? Здесь можно выполнить некоторый код js. Я думаю, можно было бы также загрузить jQuery. – stej

+0

@stej Спасибо за подсказку, но я действительно не хочу добавлять какие-либо зависимости к проекту. Это одна из причин, по которой я пишу ее в Powershell. – raphinesse

ответ

0

По какой-то причине мне нужно было сделать окно браузера видимым для моего, чтобы даже удаленно работать - без него метод Navigate был невыносимо медленным, а свойство $ ie.Busy никогда, казалось бы, не возвращало ничего, кроме True. Тебе не обязательно это делать, но хорошо.

$ie.Visible = $true 

Осматривая коллекцию $ ie.Document.Scripts, вы можете проверить файл Jquery был загружен, но я никак не мог сделать эталонный $ ie.Document.parentWindow работы - которая также означает, что я могу Кажется, что и в свойствах jQuery. Это известное свойство, но, похоже, оно не заполнено ничем полезным, поскольку оно передается в PowerShell.

+0

В моем скрипте свойство document.parentWindow выглядит нормально AFAICT. Однако возвращенный объект не включает свойство jQuery. Я уже установил свойство «visible» в true в моем скрипте. Через document.scripts я также проверил, что загружен файл jQuery. Добавил его на почту ради полноты. – raphinesse

1

Несмотря на то, что я не мог понять, как работать с JQuery как с объектом, ниже, как я мог бы использовать Posh (мне пришлось положить конец первой здесь строки в том же чтобы получить форматирование кода):

function addJQuery ($browser) { 
#helper function to highlight text 
[email protected]" 
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 
[email protected]" 
    `$('a').hide(); 
"@ 

[email protected]" 
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") 
+0

Это ваш код? :) http://poshcode.org/2351 – stej

+0

Да, совпадений нет ;-). – Dirk

+0

Я выполнил ваш подход, чтобы выполнить jQuery-код через execScript. Дело в том, что execScript ничего не возвращает (по дизайну). Мне действительно нужен объект jQuery для того, что я пытаюсь сделать;) – raphinesse

1

Хотел бы я прочитать это в прошлом году. Я также пытался интегрировать или «внедрить» JQuery в среду хоста Windows Scripting. Также попробовал Powershell. Никто не работал. Однако мне удалось использовать этот объект «InternetExplorer.Application» с IE7, IE8 и теперь 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(); 
} 

После вышесказанного JQuery является вашим другом. Еще раз!!!

Я нашел эту хорошую функцию «ждать» где-то в сети:

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) 
    } 
} 

Функция навигации имеет все эти необязательные параметры

// 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 
0

Вы можете посмотреть в исходный код Invoke-JQuery. Я пробовал это, и я смог использовать jquery для манипулирования страницей, хотя я не модифицировал скрипт для добавления jquery.

1

В вашем while цикла, выражение (!$window.jQuery) всегда возвращает true потому что $window является ComObject и COM объекты не expandos как объекты JavaScript, так что даже если window.jQuery существует в JavaScript, он не будет автоматически становится видимым на $window объекте PowerShell.

Я действительно не нашел обходного пути, чтобы сделать jQuery объектами, доступными в powershell, и мне также интересно узнать, есть ли способ сделать это. См. this и this вопрос, который я создал на этом.

Но я полагал, что этот трюк для запуска JavaScript/JQuery на веб-странице и получить некоторые результаты обратно со страницы в 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 
Смежные вопросы