Beta 42

Research and Development

Menu

PowerShell - Adding Progress to Long-Running Cmdlets

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.

$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()
}