2017-05-03 78 views
3

我有一個foreach循環,我想表明的進展:時顯示進度環

1..254 | ForEach-Object {Test-Connection -ErrorAction SilentlyContinue -count 
1 -TimeToLive 32 "$ipcut.$_"} 
#^need to get a progress bar somewhere here^ 

我已經使用在上面的代碼不同的地方寫進度試過了,似乎並不能得到它工作,因爲它從1-254循環。

+0

不知道爲什麼會有人下來票這個問題。它符合標準,並且之前從我以前的搜索中沒有詢問過。 – systech

回答

5

這樣的事情?

$ipCut ='192.168.1' ### not included in the original question 

$arrTest = 1..254 
$all = $arrTest.Count 
$i = 0 
$arrTest | ForEach-Object { 
    Write-Progress -PercentComplete (
     $i*100/$all) -Activity "PINGs completed: $i/$all" -Status 'Working' 
    Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_" 
    $i++ 
} 

參考:Write-Progress cmdlet

Write-Progress cmdlet顯示在描繪一個正在運行的命令 或腳本的狀態在Windows PowerShell命令窗口中的進度條。您可以選擇條形反映的指標以及進度條上方和下方顯示的文字。

編輯:重寫上述代碼作爲一個班輪非常簡單:僅通過分號(;)分離特定命令,而不是換行:

$arr=1..254; $all=$arr.Count; $i=0; $arr|ForEach-Object{Write-Progress -PercentComplete ($i*100/$all) -Activity "PINGs completed: $i/$all" -Status 'Working'; Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_"; $i++} 

或簡單通過硬編碼1..254的和254代替$arr$all,分別爲:

$i=0; 1..254|ForEach-Object{Write-Progress -PercentComplete ($i*100/254) -Activity "PINGs completed: $i/254" -Status 'Working'; Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_"; $i++} 
+0

這顯然有效,但不是我正在尋找的。我想將寫入過程集成到上面的現有代碼中(請參閱問題)。重新格式化會很好,但我需要它是一個單一的聲明。 – systech

1

你不能真正增加一個進度條,並保持你的代碼作爲一個單獨的語句,但你可以做到這一點在一行經由分號分隔所需的命令:

1..254 | ForEach-Object -Begin {$i = 0} -Process {Write-Progress -PercentComplete ($i/254*100) -Activity "Tests completed: $i/254" -Status "Testing $ipcut.$_"; Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_"; $i++} 

這將使用-Begin塊在ForEach-Object命令中將計數器$i初始化爲0.根據註釋,使用這種方法,我們必須硬編碼集合的總數,因爲無法從ForEach-Object循環內以編程方式確定它,因爲每次迭代都會執行與集合中的單個項目。這主要是有問題的,因爲你在數字範圍內滾動,就好像你在一個集合中滾動,我們可以使用該集合的.count屬性來確定總數。

然而,它也是值得注意的,你不已經在所有使用Write-Progress顯示進度條。你可以用它來向用戶顯示一條消息(沒有任何移動進度條),它至少仍然表現出進步(只是沒有多大的工作量)。這樣做可以簡化代碼:

1..254 | ForEach-Object {Write-Progress -Activity "Testing $ipcut.$_"; Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_"} 
2

Josef Z.'s helpful answer向您展示了一個可行的解決方案。

你的具體願望簡單地通過插入一個Write-Progress命令加入到現有的命令的ForEach-Object腳本塊得到一個進度條是不可能的,但是:

腳本程序塊傳遞給ForEach-Object沒有事先知道方式有多少物體將通過管道傳遞,這是顯示百分比方面進展的先決條件。

必須確定迭代次數提前的時間。

如果你想概括這一點,使用功能,如下面的(故意保持簡單):

function Invoke-WithProgress { 
    param(
    [scriptblock] $Process, 
    [string]  $Activity = 'Processing' 
) 
    # Collect the pipeline input ($Input) up front in an array list. 
    $al = New-Object System.Collections.ArrayList 100 # 100 is the initial capacity 
    foreach ($o in $Input) { $null = $al.Add($o) } 
    # Count the number of input objects. 
    $count = $al.Count; $i = 0 
    # Process the input objects one by one, with progress display. 
    $al | ForEach-Object { 
    Write-Progress -PercentComplete ((++$i)*100/$count) -Activity "$Activity $i/$count..." 
    . $Process 
    } 
} 

再次注意,所有的管道輸入收集前面

在你的情況,你會調用它,如下所示:

1..254 | Invoke-WithProgress { 
Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_" 
}