今天踩到的雷,PowerShell Invoke-WebRequest 讀取某個網頁會當掉沒反應,必須按 Ctrl-C 才能脫逃,但如果寫 (Invoke-WebRequest -Uri ...).Content 卻可以馬上取回結果。

被卡住了好一陣子,爬文查到線索,Invoke-WebRequest 預設會用 IE 引擎將 Content 內容解析為 HTML DOM 放入 ParsedHtml 屬性,當 HTML 包含某些特殊內容導致解析出錯,試圖存取 ParsedHtml 便會卡住。Invoke-WebRequest -Uri ... 顯示所有屬性包含 ParsedHtml 因此當住;(Invoke-WebRequest -Uri ...).Content 時未讀取 ParsedHtml 故可順利執行。

花了點時間,我用消去法找出能重現問題的最小範例。示範出錯狀況以下,輸入 Invoke-WebRequest -Uri "http://localhost/aspnet/freezeinvokewebreq.html" 會沒回應,需按 Ctrl-C 跳出;而 (Invoke-WebRequest -Uri "http://localhost/aspnet/freezeinvokewebreq.html").Content 則馬上顯示結果:

解決方法不難,有個 Invoke-WebRequest -UseBasicParsing 參數可停用 DOM 解析,除非有用到 ParsedHtml 否則加上 -UseBasicParsing 可節省解析時間又避開當掉風險,百利無害。而 PS6.0+ 起改為永遠採用 Basic Parsing (因為要跨平台且 IE 已非標準內建元件),保留 -UseBasicParsing 參數僅為向前相容已無作用,將來不再會遇到這種狀況。至於 PS 4/5,若遇到卡住情況,可優先考慮以上可能。

Case of Invoke-WebRequest hang while calling specific webpage. It turns out that some specific HTML content may cause ParsedHtml property failed, the workaround is adding -UseBasicParsing argument.


Comments

Be the first to post a comment

Post a comment