2017-05-03 24 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.$_" 
}