我有一个想要显示进度的ForEach循环:
1..254 | ForEach-Object {Test-Connection -ErrorAction SilentlyContinue -count
1 -TimeToLive 32 "$ipcut.$_"}
#^need to get a progress bar somewhere here^
我已尝试在上面的代码中的各个地方使用write-progress,并且似乎无法使其工作,因为它从1-254循环。
答案 0 :(得分: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在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++}
答案 1 :(得分:3)
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.$_"
}
答案 2 :(得分: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++}
这使用ForEach-Object命令中的-Begin
块将计数器$i
初始化为0.根据评论,使用这种方法我们必须对集合的总数进行硬编码,因为那里&#39 ;无法从ForEach-Object循环中以编程方式确定它,因为每次迭代都会处理集合中的单个项目。这主要是有问题的,因为你在一个数字范围内管道,就像你在一个集合中管道一样,我们可以使用该集合的.count
属性来确定总数。
但是,值得注意的是,您 您可以使用它向用户显示一条消息(没有移动进度条),该消息至少仍然可以显示进度(而不是您的总工作量)。这样做可以简化代码:
Write-Progress