Windows PowerShell每周提示(33):创建进度栏
在使用脚本(及使用Windows PowerShell)时,最美妙的一件事是多数任务会像你执行脚本那样很快就会完成。需要计算机上所有服务的信息?那么使用Windows PowerShell,输入以下内容并按下回车:
当按下回车后,有关服务的信息就开始在屏幕上出现,这个过程在它结束之前将持续一两秒左右。能如此迅速的获得有关服务的信息的确很不错,同时,你也不必提供任何形式的进度条来使用户相信脚本已经开始运行,对编写脚本的人来说这一点也很不错。
当然,并不是所有的脚本(或者命令)会如此快速的运行。迟早你会遇到需要30秒或更多时间才能运行完成的操作。万一遇到这种情况,对你来说给用户适当的反馈是合适的,这可以让用户知道:
1) 脚本正在运行(也就是说脚本没有挂起)
2) 进程正在执行中
这很不错,除了你在显示进度栏时有可能会遇到很多麻烦。
当然,事实证明,也没有太多麻烦:
| $colFiles = Get-ChildItem C:\Windows -include *.dll –recurse foreach ($objFile in $colFiles) { $i++ $intSize = $intSize + $objFile.Length Write-Progress -activity "Adding File Sizes" -status "Percent added: " -PercentComplete (($i / $colFiles.length) * 100) } $intSize = "{0:N0}" -f $intSize Write-Host "Total size of .DLL files: $intSize bytes." |
正如我们早先所说的,除非你的脚本将运行一段时间才能完成,否则没有理由在脚本中包含进度栏。在屏幕上显示进度栏随后又很快消失是没有意义的。示例脚本所选择的任务是:将从Windows文件夹及其子文件夹中提取.DLL文件的信息,并将每个文件的大小累加起来,最后回显所有.DLL 文件累加起来的总大小。此任务虽然也不需要很长时间就能完成,但完成任务所需要的时间是值得使用进度栏的。。
为了完成这个任务,我们所做的第一件事是提取一个包含所有.DLL文件的集合,也就是以下这行代码所要完成的事:
| $colFiles = Get-ChildItem C:\Windows -include *.dll –recurse |
对从Windows文件夹及其子文件夹中提取.DLL文件的信息这个任务本身而言,它只需几秒钟就能完成。然而我们不在提取文件信息时显示进度栏。为什么?一个简单的理由是:我们做不到。进度栏需要在类似循环语句的结构中被显示及刷新。不论这样做是好是坏,进度栏无法在单个命令(比如调用Get-ChildItem)的处理过程中显示及更新。
一旦我们提取完所有.DLL文件的信息,我们就可以建立一个foreach循环来遍历集合中的每一项。那我们在循环内做了些什么呢?对初学者而言,我们打算每运行一次循环就在计数器变量$i的值上累加上1:
因为我们还没有引用$i,所以它从0开始计数。从0增加到1使得$i的值等于1.值1也代表了我们运行过的循环的数量。很巧?我们不这么认为……
当刷新过计数器变量后,我们随后将集合中的第一个文件的大小(Length)添加到另一个名为intSize的计数器变量中:
| $intSize = $intSize + $objFile.Length |
此时我们创建了一个进度栏,这意味着是时候更新我们的进度栏了。也就是以下这行代码所要完成的:
| Write-Progress -activity "Adding File Sizes" -status "Percent added: " -percentComplete (($i / $colFiles.length) * 100) |
那么这里发生了什么?好的,这里我们使用Write-Progress cmdlet在屏幕上显示进度栏。并传递给Write-Progress三个参数:
l -activity. 本参数代表进度栏的标题。(过一会你就知道我们所说的是什么了。)我们正在累加所有文件的大小所以我们将该参数设为Adding File Sizes
l -status. 本参数描述当前活动的状态。在本例中,该参数代表要报告其进度的活动的当前状态的字符串。对本脚本而言我们只是将字符串Percent added赋值给该参数:
l -percentComplete. 本参数代表已完成任务的百分比。对本脚本而言很容易计算该值。这是因为我们确切知道在集合中有多少个文件。(怎么知道的呢?因为$colFiles集合的Length属性告诉我们在集合中有多少文件。)为了知道完成的百分比我们将已完成数(计数器变量$i)除以总文件数($colFiles.length)。然后再将该值乘以100.
然后,当我们刷新进度栏后,我们返回循环顶部并对集合中的下一个文件重复此过程。在屏幕上这个过程看起来像这样:
这不是蒙娜丽莎或者米洛的维纳斯,但是这并不坏。相比这两者,它在跟踪脚本的执行过程上做的更好。(米洛的维纳斯甚至没有手指来数数。)
本文将给你使用Write-Progress cmdlet和PowerShell内置的进度栏带来启发。更多信息请参阅PowerShell的帮助文件:
| Get-Help Write-Progress -full |
对脚本专家而言,我们本周任务的完成度也到100%了。各位,我们下周见。
英文原文
http://www.microsoft.com/technet/scriptcenter/resources/pstips/mar08/pstip0321.mspx