突發奇想,如果手上有個現成 Command Line 的監控性質程式(.EXE),會在執行過程即時輸出事件或統計資訊,有沒有可能把它接進 PowerShell Pipeline 即時分析並做出回應呢?

舉個例子,像是 ping -t IP 每隔一秒回報一次測試結果,就是很好的範例! 當然,用 PowerShell 用 PING 測網路有點捨近求遠,但 ping -t 8.8.8.8 每秒一次源源不斷輸出檢測報告,又可透過停用啟用網卡操縱結果,是絕佳的練習對象。

第一步,我們先分析網路有通跟不通的結果特徵:

事實上我們只要比對有通的特徵即可,例如:要出現 TTL= 字樣,若沒有就代表網路不通。

那要怎麼把 ping 的結果串接到 PowerShell 呢?方法出奇簡單 - . cmd.exe /c 'ping -t 8.8.8.8' | ForEach-Object { $_ },這樣就可以了,$_ 會是 ping 輸出的文字內容,一次一行。

有了以上知識背景,要寫個即時偵測 Internet 連線狀態的 PowerShell 小工具已是小事一椿:(實測在網路品質略差的環境正常回應間偶爾會夾雜一兩次 Request timed out, 為避免觸發假警報,我加入要連續失敗三次才發斷線警告的邏輯)

$start = $false
$connected = $true
$failCount = 0 # 統計失敗次數
$threshold = 3 # 連續失敗三次才判定斷線,減少瞬斷假警告
. cmd.exe /c 'ping -t 8.8.8.8' | ForEach-Object {
    if ([string]::IsNullOrEmpty($_)) {
        return
    }
    if (!$start) {
        if ($_.StartsWith('Ping')) { # Ping 起首文字的下一列才是狀態
            $start = $true
        }
    }
    else {
        if ($_.Contains('TTL=')) {
            if (!$connected) {
                Write-Host "網路恢復" -ForegroundColor Green
            }
            else {
                $failCount = 0
            }
            $connected = $true
        } 
        else {
            if ($connected) {
                $failCount++
                if ($failCount -ge $threshold) {
                    Write-Host "網路中斷" -ForegroundColor Red
                    $connected = $false
                }
                else {
                    # 偵錯資訊
                    Write-Host "失敗次數累計 - $failCount" -ForegroundColor DarkGray
                    Write-Host $_ -ForegroundColor DarkGray
                }
            }
        }
    }
}

測試成功!

掌握這個技巧,未來就有機會用 PowerShell 整合一些獨門 EXE 工具,玩出更多花式應用。

Example of connecting output stream of EXE to PowerShell pipeline and processing it line by line.


Comments

Be the first to post a comment

Post a comment