我有一个foreach循环,我想表明的进展:时显示进度环
1..254 | ForEach-Object {Test-Connection -ErrorAction SilentlyContinue -count
1 -TimeToLive 32 "$ipcut.$_"}
#^need to get a progress bar somewhere here^
我已经使用在上面的代码不同的地方写进度试过了,似乎并不能得到它工作,因为它从1-254循环。
我有一个foreach循环,我想表明的进展:时显示进度环
1..254 | ForEach-Object {Test-Connection -ErrorAction SilentlyContinue -count
1 -TimeToLive 32 "$ipcut.$_"}
#^need to get a progress bar somewhere here^
我已经使用在上面的代码不同的地方写进度试过了,似乎并不能得到它工作,因为它从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++
}
的
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++}
这显然有效,但不是我正在寻找的。我想将写入过程集成到上面的现有代码中(请参阅问题)。重新格式化会很好,但我需要它是一个单一的声明。 – systech
你不能真正增加一个进度条,并保持你的代码作为一个单独的语句,但你可以做到这一点在一行经由分号分隔所需的命令:
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.$_"}
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.$_"
}
不知道为什么会有人下来票这个问题。它符合标准,并且之前从我以前的搜索中没有询问过。 – systech