在 Windows 服务器上的 Internet Explorer 中使用 PowerShell 运行 Javascript

Using PowerShell to run Javascript in Internet Explorer on Windows Server

我有一段 PowerShell 脚本:

$IE = New-Object -com InternetExplorer.Application
$IE.Navigate($URL)
While ($IE.ReadyState -Ne 4) {Start-Sleep -Milliseconds 100}
$IE.Document.ParentWindow.ExecScript("var JSIEVariable = new XMLSerializer().serializeToString(document);", "javascript")
$Obj = $IE.Document.ParentWindow.GetType().InvokeMember("JSIEVariable", 4096, 
$Null, $IE.Document.parentWindow, $Null)
$HTML = $Obj.ToString()
$IE.Quit()

在 Windows 10 上它工作正常但在 Windows Server 2016 上第 4、5 和 6 行我收到错误:

You cannot call a method on a null-valued expression.

我很确定它与 Windows 服务器中的额外安全性有关,阻止 IE 运行ning Javascript。必须有某种方法可以降低安全性,使其与 Windows 10 更加一致,这样该脚本才能正确地 运行,但我不知道如何实现。我关闭了 IE 增强安全配置并确保启用了活动脚本。除此之外我不知道还能做什么。

这可能与 Internet Explorer 有关 'protected mode'。 如果 IE 确实处于保护模式,$IE 对象在 .Navigate() 命令之后丢失,之后的任何操作都会导致错误 You cannot call a method on a null-valued expression.

为了解决这个问题,这里有一个尝试重新连接 $IE 对象的函数。

function Connect-InternetExplorer {
    # creates a new 'InternetExplorer.Application' object and navigates to the given url.
    # If IE is in 'protected mode', the function tries to reconnect using the window handle
    [CmdletBinding()]
    param(
        [Parameter(ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Mandatory = $true, Position = 0)]
        $Url,

        [switch]$Visible
    )
    # test if Internet Explorer is in 'Protected Mode'
    # see https://www.lifewire.com/how-to-disable-protected-mode-in-internet-explorer-2624507
    $ieProtectedMode = ((Get-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones' -Name '2500').2500 -ne 3)

    $ie = New-Object -ComObject 'InternetExplorer.Application' -ErrorAction SilentlyContinue
    $ie.Visible = [bool]$Visible
    $ie.Silent = $true
    $hwnd = $ie.Hwnd
    $ie.Navigate($Url)

    if ($ieProtectedMode) {
        $oldErrorActionPreference = $ErrorActionPreference
        $ErrorActionPreference = 'Stop'

        $objShell = New-Object -ComObject 'Shell.Application'
        Start-Sleep -Milliseconds 100
        try {
            $ie = $objShell.Windows() | Where-Object {$_.HWND -eq $Hwnd}
            $ie.Visible = [bool]$Visible
        }
        catch {
            # sometimes the Shell.Application does not find the window quickly enough,
            Start-Sleep -Milliseconds 500
            try {
                $ie = $objShell.Windows() | Where-Object {$_.HWND -eq $Hwnd}
                $ie.Visible = [bool]$Visible
            }
            catch {
                Write-Warning "Could not connect to the InternetExplorer ComObject."
            }
        }
        finally {
            $ErrorActionPreference = $oldErrorActionPreference
            # clean up the Com object
            [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objShell) | Out-Null
            [System.GC]::Collect()
            [System.GC]::WaitForPendingFinalizers()
        }
    }

    if (!$ie) { return $null }
    while ($ie.Busy -eq $true) { Start-Sleep -Milliseconds 50 }
    return $ie
}

# this replaces the first three lines of your original code
$IE = Connect-InternetExplorer -Url $URL
if ($IE) {
    $IE.Document.ParentWindow.ExecScript("var JSIEVariable = new XMLSerializer().serializeToString(document);", "javascript")
    $Obj = $IE.Document.ParentWindow.GetType().InvokeMember("JSIEVariable", 4096, $Null, $IE.Document.parentWindow, $Null)
    $HTML = $Obj.ToString()
    $IE.Quit()

    # clean up the $IE Com object
    [System.Runtime.Interopservices.Marshal]::ReleaseComObject($IE) | Out-Null
    [System.GC]::Collect()
    [System.GC]::WaitForPendingFinalizers()
}
else {
    Write-Warning "Could not connect Internet Explorer"
}

希望对您有所帮助

一位同事帮我解决了这个问题。它与 IE 安全没有任何关系,至少与尚未涵盖的任何内容无关。问题是 GAC 中缺少 'Microsoft.mshtml.dll'。它不会出现在 Windows 服务器的全新安装中,但安装 Office 或 Visual Studio 之类的东西会添加它。但是,我敢打赌,大多数人 运行 一个 Windows 服务器不会仅仅为了让它正常工作而这样做。我所做的是将以下 folder/file 结构从我的 Windows 10 PC 复制到我的服务器,关闭 PowerShell 和 ISE 的所有实例,当我再次打开 PowerShell 时 运行 脚本一切正常.

C:\Windows\assembly\GAC\Microsoft.mshtml C:\Windows\assembly\GAC\Microsoft.mshtml.0.3300.0__b03f5f7f11d50a3a C:\Windows\assembly\GAC\Microsoft.mshtml.0.3300.0__b03f5f7f11d50a3a\Microsoft.mshtml.dll C:\Windows\assembly\GAC\Microsoft.mshtml.0.3300.0__b03f5f7f11d50a3a__AssemblyInfo__.ini