IE COM automation: How to get the return value of

2019-01-29 10:52发布

问题:

From this other post it looks like it is possible to get the return value of IHTMLWindow2::execScript from Internet Explorer API, however the linked example is in C++ and I don't really understand it. I'm trying to do the same thing in PowerShell, so here's my code that shows the problem:

$ie = New-Object -COM InternetExplorer.Application
$ie.visible = $true
$ie.navigate("http://google.com")
while ( $ie.busy ) { start-sleep -m 100 }
$document = $ie.document
$window = $document.parentWindow

Function eval($jsCommand) {
    # Of course it doesn't return anything here. How can I get the return value?
    return $window.execScript($jsCommand, 'javascript')
}

eval 'parseInt("12")' # returns nothing

What I'm really trying to do is to make jQuery selector/objects available in my PowerShell script, so that I can do things like:

eval '$("input#selector")' | where name -eq 'username'

and more.

Update: Look at this Gist for PowerShell function to run JavaScript/JQuery and return results back to PS, with timeout. It was extended from the answer below.

回答1:

The preferred method is probably what @Matt suggested to use the eval method instead of execScript which has been deprecated in IE11. However, I still couldn't find how to access that eval from IE API. I created this other question to follow up with that.

I could, however, figure a way to execute JavaScript/jQuery on a web page and return the results back to PowerShell with this trick that we store the JavaScript return value in the DOM using setAttribute and then retrieving it in PowerShell using getAttribute.

# 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