Parsing local HTML file using new -ComObject "HTMLFile" broken?

I have a script password expired in 6 months without any problem. The script will read in a static html file and change around some content in memory and then the html email will be sent to all users who have passwords expiring.

The script seems to have broken in the last week or so. After further investigation, I narrowed down the errors to a section where Powershell should create a new ComObject and write that HTML file to the ComObject.

Now I am getting the error:

No coercion operator is defined between types 'System.Array' and 'System.String'
At line:1 char:1
+ $html.write($source);
+ ~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException

      

The above error occurs when I run the lines below:

$html = New-Object -ComObject "HTMLFile"
$src = Get-Content -path "./passwordreminder.html" -Raw
$html.write($src)

      

When I call the method write()

, I get the error.

Since it has been working fine for the last 6 months, the only thing I can think of has changed is my powershell version. I believe that when I started using this script, I was using Powershell v4.0, but after Windows Updates, I assume Powershell is now in 5.0. See below:

Name                           Value
----                           -----
PSVersion                      5.0.10105.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.34209
BuildVersion                   10.0.10105.0
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3

      

The script runs on Windows Server 2012 R2 OS.

Does anyone have any idea?

I've seen some suggestions for other questions calling for a method IHTMLDocument2_write()

on a ComObject, but that method doesn't exist when I try to call it.

Update:

I was able to confirm that it was INDEED BROKEN in my Powershell version.

I was just able to test the same code on another server with the same OS but below Powershell version:

Name                           Value
----                           -----
PSVersion                      4.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.34014
BuildVersion                   6.3.9600.17090
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0}
PSRemotingProtocolVersion      2.2

      

And the code works as expected.

Does anyone know what can be used in this new version of Powershell?

+3


source to share


3 answers


You can try with the Internet Explorer COM Object:

$ie = New-Object -COM 'InternetExplorer.Application'

$ie.Navigate("file://$($PWD.Path)/passwordreminder.html")
do {
  Start-Sleep -Milliseconds 100
} until ($ie.ReadyState -eq 4)

# do stuff

      

I don't have PowerShell v5 so I can't check. If HTMLFile doesn't work, it might as well.



You can call the method Navigate()

(and the loop waiting for the page to finish loading) in the outer loop if you need to rerun it.

$ie = New-Object -COM 'InternetExplorer.Application'

foreach (...) {
  $ie.Navigate("file://$($PWD.Path)/passwordreminder.html")
  do {
    Start-Sleep -Milliseconds 100
  } until ($ie.ReadyState -eq 4)

  # do stuff
}

      

+1


source


This seems to work correctly if you specify a UCS-2 byte array instead of a string:



$html = New-Object -ComObject "HTMLFile"
$src = Get-Content -path "./passwordreminder.html" -Raw
$src = [System.Text.Encoding]::Unicode.GetBytes($src)
try
{
    # This works in PowerShell 4
    $html.IHTMLDocument2_write($src)
}
catch
{
    # This works in PowerShell 5
    $html.write($src)
}

      

+1


source


Solved by adding a path reference and specifying the object type

Add-Type -Path "C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll"

$webpage = New-Object mshtml.HTMLDocumentClass

      

Here is the complete code

$url = 'http://website'
$outFile = 'C:\content.txt'
$showCount = 10;

[net.httpwebrequest]$httpwebrequest = [net.webrequest]::create($url)
[net.httpWebResponse]$httpwebresponse = $httpwebrequest.getResponse()
$reader = new-object IO.StreamReader($httpwebresponse.getResponseStream())
$html = $reader.ReadToEnd()
$reader.Close()

Add-Type -Path "C:\Program Files (x86)\Microsoft.NET\Primary Interop Assemblies\Microsoft.mshtml.dll"


$webpage = New-Object mshtml.HTMLDocumentClass
$webpage.IHTMLDocument2_write($html)

$topicElements = $webpage.documentElement.getElementsByClassName('topic')

$time = (Get-Date).ToString("yyyy-MM-dd HH:mm:ss")
$content = '[www.hkgalden.com] [' + $time + '] '

$i = 0;
foreach ($topicElement in $topicElements) {
    $titleElement = $topicElement.getElementsByClassName('title')[0].getElementsByTagName('a')[0]
    $title = $titleElement.innerText

    $usernameElement = $topicElement.getElementsByClassName('username')[0]
    $username = $usernameElement.innerText

    $content += $username + ': ' + $title + ' // '
    $i++
    if ($i -gt $showCount) {
        break
    }
}
#$content
$content | Out-File -Encoding utf8 $outFile

      

0


source







All Articles