Adding Progress to Long-Running Cmdlets

Share |

Join PowerShell.com!
Subscribe to Feed

PowerShell eBook
Sign up for
Your PowerTip of the Day:

Powershell Plus


13 Free SQL Tools from Idera


Free Ebook: Mastering Powershell

Sometimes cmdlets take some time, and unless they emit data, the user gets no feedback. Here are three examples for calls that take a long time without providing user feedback:

$hotfix = Get-Hotfix
$products = Get-WmiObject Win32_Product
$scripts = Get-ChildItem $env:windir *.ps1 -Recurse -ea 0

To provide your scripts with better user feedback, here's a function called Start-Progress. It takes a command and then executes it in a background thread. The foreground thread will output a simple progress indicator. Once the command completes, the results are returned to the foreground thread.

It's really simple and can make a heck of a difference to the user:

$hotfix = Start-Progress {Get-Hotfix}
$products = Start-Progress {Get-WmiObject Win32_Product}
$scripts = Start-Progress {Get-ChildItem $env:windir *.ps1 -Recurse -ea 0}

And here's the function code you need:

function Start-Progress {
  param(
    [ScriptBlock]
    $code
  )
  
  $newPowerShell = [PowerShell]::Create().AddScript($code)
  $handle = $newPowerShell.BeginInvoke()
  
  while ($handle.IsCompleted -eq $false) {
    Write-Host '.' -NoNewline
    Start-Sleep -Milliseconds 500
  }
  
  Write-Host ''
  
  $newPowerShell.EndInvoke($handle)
  
  $newPowerShell.Runspace.Close()
  $newPowerShell.Dispose()
}

Twitter This Tip! ReTweet this Tip!


Posted Apr 20 2012, 06:00 AM by ps1

Comments

Anders wrote re: Adding Progress to Long-Running Cmdlets
on 04-22-2012 1:32 PM

Just what the doctor ordered! :-)

I had to do a little fine-tuning to make it extra user-informative:

function Start-Progress {

  param(

    [parameter(mandatory=$true)]

[ScriptBlock] $Code,

[parameter(mandatory=$false)]

[string] $Statusmessage

 )

  $newPowerShell = [PowerShell]::Create().AddScript($Code)

  $handle = $newPowerShell.BeginInvoke()

if (-not [string]::IsNullOrEmpty($Statusmessage)){ Write-Host $Statusmessage -NoNewline -ForegroundColor DarkCyan}

  while ($handle.IsCompleted -eq $false) {

    Write-Host '.' -NoNewline -ForegroundColor DarkCyan

    Start-Sleep -Milliseconds 500

  }

  Write-Host ' Done' -NoNewline -ForegroundColor DarkCyan

Write-Host ''  

$newPowerShell.EndInvoke($handle)  

  $newPowerShell.Runspace.Close()

  $newPowerShell.Dispose()

}

clear

$hotfix = Start-Progress {Get-Hotfix} -Statusmessage "Inventoring hotfixes"

$products = Start-Progress {Get-WmiObject Win32_Product} -Statusmessage "Inventoring installed products"

$lookHere = $env:windir

$scripts = Start-Progress {Get-ChildItem $lookHere *.ps1 -Recurse -ea 0} -Statusmessage "Inventoring Powershellfiles found in '$lookHere'"

Irwin Strachan wrote re: Adding Progress to Long-Running Cmdlets
on 04-23-2012 3:32 AM

Nice !!!

Copyright 2012 PowerShell.com. All rights reserved.