2015-06-20 36 views
3

我一直在運行密碼過期腳本的傳遞6個月沒有任何問題。該腳本將讀取一個靜態html文件並更改內存中的一些內容,然後將發送一封html電子郵件給所有過期密碼的用戶。使用New-Object -ComObject解析本地HTML文件「HTMLFile」壞了?

劇本似乎在過去的一週左右破了。經過進一步調查,我已經將錯誤範圍縮小到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更新之後,我猜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 BROKEN

我只是能夠使用相同的操作系統,但低於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中使用什麼嗎?

+1

你可以嘗試一個IE對象:'$ ie = New-Object -COM'InternetExplorer.Application'; $ ie.Navigate(「file:// $($ PWD.Path)/passwordreminder.html」'。我沒有PowerShell v5,所以我無法測試。如果'HTMLFile'被破壞,這可能會 –

+1

在工作服務器和非工作服務器上都可以將違規行更改爲'$ html.Write;',運行它並比較結果?這將輸出哪些重載的Write方法可用在'$ html'對象上,也許有一個新的可用,PowerShell現在試圖調用「錯誤」的。 – BACON

+0

@Ansgar感謝,仍然可以在v5.0 !!!!我能夠重寫部分腳本使用這種方法,但是這種方法當然並不理想,腳本會編輯內存中的HTML文檔,以便每個用戶都有一個即將到來的密碼,這意味着我必須爲每個人啓動一個新的IE進程。在某些日子裏可以達到20-30 +進程,我可以通過運行一個「停止進程」來殺死其中的一些進程,但仍然會比較大到以前的工作解決方案。我會用這個,直到我能找到更好的解決方法。謝謝!!!! – kevin

回答

1

你可以用一個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 
} 
+0

** Powershell的V4.0:** MemberType:方法 OverloadDefinitions:{無效寫(SAFEARRAY(變體)) TypeNameOfValue:System.Management.Automation.PSMethod 值:空隙寫(SAFEARRAY(變體)) 名稱:寫 IsInstance:真 ** Powershell的V5.0:** MemberType:方法 OverloadDefinitions:{無效寫(SAFEARRAY(變體))} TypeNameOfValue:System.Management.Automation.PSMethod 值:空隙寫(SAFEARRAY(Variant)) 姓名:寫 IsInstan ce:True – kevin

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 
0

這似乎正常工作,如果你提供了一個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) 
} 
+0

我試過這個,但得到了異常:**異常調用「1」參數的「寫」:「類型不匹配** – kevin

+0

我改變了這個使用我的工作代碼(它適用於兩個PowerShell 4和5)。我猜你沒有使用PowerShell 5? – jedigo