6

パスの 6 か月間、問題なくパスワード有効期限スクリプトを実行しています。スクリプトは静的な html ファイルを読み取り、メモリ内のコンテンツの一部を変更します。その後、有効期限が切れるパスワードを持つすべてのユーザーに html メールが送信されます。

このスクリプトは、過去 1 週間程度で壊れたようです。さらに調査した結果、Powershell が新しい ComObject を作成し、その HTML ファイルを ComObject に書き込むセクションにエラーを絞り込みました。

エラーが発生しました:

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

以下のコード行を実行すると、上記のエラーが発生します。

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

write()メソッドを呼び出すと、エラーが発生します。

過去 6 か月間正常に動作していたため、変更されたと考えられる唯一のことは、私のバージョンの powershell です。このスクリプトの実行を開始したとき、私は Powershell v4.0 を使用していたと思いますが、Windows Update の後、Powershell は現在 v5.0 になっていると思います。下記参照 :

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

スクリプトは Windows Server 2012 R2 OS で実行されています。

誰にもアイデアはありますか?

ComObject でメソッドを使用するように呼び出す他の質問でいくつかの提案を見てきましたIHTMLDocument2_write()が、このメソッドを呼び出そうとすると存在しません。

アップデート :

私のバージョンの Powershell では、これがINDEED BROKENであることを確認できました。

同じOSでPowershellのバージョン以下の別のサーバーで同じコードをテストできました:

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

そして、コードは期待どおりに機能します。

この新しいバージョンの Powershell で何が使用できるか知っている人はいますか?

4

4 に答える 4

5

文字列の代わりに UCS-2 バイト配列を指定すると、これは適切に機能するようです。

$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)
}
于 2016-05-22T22:39:51.997 に答える
2

Internet Explorer COM オブジェクトで試すことができます。

$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

ただし、PowerShell v5 を持っていないため、テストできません。HTMLFile が壊れている場合は、これも同様です。

Navigate()繰り返し実行する必要がある場合は、外側のループでメソッド (およびページの読み込みが完了するのを待つループ) を呼び出すことができます。

$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
}
于 2015-06-20T21:17:24.190 に答える
0

パス参照を追加し、オブジェクトのタイプを指定することで解決

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

$webpage = New-Object mshtml.HTMLDocumentClass

ここに完全なコードがあります

$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
于 2016-04-24T05:23:31.030 に答える