在 For 循环期间显示进度
Showing Progress during For Loop
我有一个要显示进度的 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 循环。
是这样的吗?
$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++
}
The Write-Progress
cmdlet displays a progress bar in a Windows
PowerShell command window that depicts the status of a running command
or script. You can select the indicators that the bar reflects and the
text that appears above and below the progress bar.
编辑:将上面的代码重写为一行很容易:只需用分号 (;
) 代替换行符分隔特定的命令:
$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..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。根据评论,使用这种方法我们必须对集合的总数进行硬编码,因为无法从 ForEach-Object 循环中以编程方式确定它,因为每次迭代都处理集合中的单个项目。这主要是有问题的,因为你在一个数字范围内管道,就像你在一个集合中管道一样,我们可以使用该集合的 .count
属性 来确定总数。
但是,同样值得注意的是,您 根本没有 显示进度条来使用 Write-Progress
。您可以只使用它向用户显示一条消息(没有移动的进度条),它至少仍然显示进度(只是不是您的总工作完成了多长时间)。这样做可以将代码简化为:
1..254 | ForEach-Object {Write-Progress -Activity "Testing $ipcut.$_"; Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_"}
显示了一个可行的解决方案。
您想要通过将 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,
# using @(...) to force enumeration.
$a = @($Input)
# Count the number of input objects.
$count = $a.Count; $i = 0
# Process the input objects one by one, with progress display.
$a | 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.$_"
}
我有一个要显示进度的 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 循环。
是这样的吗?
$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++
}
The
Write-Progress
cmdlet displays a progress bar in a Windows PowerShell command window that depicts the status of a running command or script. You can select the indicators that the bar reflects and the text that appears above and below the progress bar.
编辑:将上面的代码重写为一行很容易:只需用分号 (;
) 代替换行符分隔特定的命令:
$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..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。根据评论,使用这种方法我们必须对集合的总数进行硬编码,因为无法从 ForEach-Object 循环中以编程方式确定它,因为每次迭代都处理集合中的单个项目。这主要是有问题的,因为你在一个数字范围内管道,就像你在一个集合中管道一样,我们可以使用该集合的 .count
属性 来确定总数。
但是,同样值得注意的是,您 根本没有 显示进度条来使用 Write-Progress
。您可以只使用它向用户显示一条消息(没有移动的进度条),它至少仍然显示进度(只是不是您的总工作完成了多长时间)。这样做可以将代码简化为:
1..254 | ForEach-Object {Write-Progress -Activity "Testing $ipcut.$_"; Test-Connection -ErrorAction SilentlyContinue -count 1 -TimeToLive 32 "$ipcut.$_"}
您想要通过将 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,
# using @(...) to force enumeration.
$a = @($Input)
# Count the number of input objects.
$count = $a.Count; $i = 0
# Process the input objects one by one, with progress display.
$a | 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.$_"
}