Foreground/Background Swappable Downloads in PowerShell

Here's another interesting use for my PowerShell Eventing Snap-In, where I'm simulating unix-style foreground/background tasks. In this case, the task is a large download using System.Net.WebClient. Just dot-source the script below and start a download using the Start-Download function, passing the url to the large file and the local path where to save your file (be sure to fully qualify the save path). The download will start immediately and show a progress bar with bytes remaining and a percentage, however you can hit Ctrl+C at any time and the download will continue in the background. You can get back to PowerShell tasks, and bring back up the progress bar by invoking Show-Progress at any time. Use Stop-Download to cancel the currently active download. Only one download can be active at a time, but this could easily be extended to support a pool of downloads (using multiple WebClient objects).

downloads.ps1 (1.85 KB)

  1. #requires -pssnapin pseventing  
  2.  
  3. function Stop-Download {  
  4.     $wc.CancelAsync()  
  5. }  
  6.  
  7. function Start-Download {  
  8.     param(  
  9.         [uri]$Url = $(throw "need Url."),  
  10.         [string]$Path = $(throw "Need save path.")  
  11.     )  
  12.  
  13.     # initialise webclient  
  14.     if (-not $global:wc) {  
  15.         $global:wc = New-Object System.Net.WebClient  
  16.         $var = get-variable wc  
  17.         Connect-EventListener -Variable $var `  
  18.             -EventName DownloadProgressChanged, DownloadFileCompleted         
  19.     }  
  20.  
  21.     if ($wc.IsBusy) {  
  22.         Write-Warning "Currently busy: Please cancel current download or wait until it is completed." 
  23.         return 
  24.     }  
  25.       
  26.     $wc.DownloadFileAsync($url, $path, $path) # last is userstate  
  27.     Write-Host "Download started. Ctrl+C to continue in background." 
  28.     Show-Progress  
  29. }  
  30.  
  31. function Show-Progress {  
  32.     if (-not $wc.IsBusy) {  
  33.         # possibly already completed, clear queue  
  34.         get-event | Out-Null 
  35.         "No active download." 
  36.         return 
  37.     }  
  38.       
  39.     Start-KeyHandler -CaptureCtrlC  
  40.       
  41.     trap [exception] {  
  42.         Stop-KeyHandler  
  43.         Write-Warning "error" 
  44.         $_ 
  45.         return 
  46.     }  
  47.       
  48.     $exiting = $false 
  49.       
  50.       
  51.     while (-not $exiting) {       
  52.         $events = @(Get-Event -Wait)          
  53.         $event = $null;  
  54.           
  55.         # skip to last event  
  56.         foreach ($event in $events) {  
  57.             if ($event.Name -eq "CtrlC") {  
  58.                 break;  
  59.             }  
  60.         }         
  61.           
  62.         switch ($event.Name) {  
  63.             "DownloadProgressChanged" {  
  64.                 $r = $event.args.BytesReceived  
  65.                 $t = $event.args.TotalBytesToReceive  
  66.                 $activity = "Downloading $($event.args.userstate)" 
  67.                 $p = [math]::Ceiling(([double]$r / $t) * 100)  
  68.                 Write-Progress -Activity $activity -PercentComplete $p `  
  69.                     -Status ("{0} of {1} byte(s)" -f $r,$t)  
  70.             }  
  71.             "DownloadFileCompleted" {  
  72.                 Write-Progress -Activity DownloadComplete -Completed  
  73.                 "Complete." 
  74.                 $exiting = $true 
  75.             }  
  76.             "CtrlC" {  
  77.                 "Switching to background downloading. Show-Progress to move to foreground." 
  78.                 $exiting = $true 
  79.             }  
  80.         }         
  81.     }  
  82.     Stop-KeyHandler  
blog comments powered by Disqus

About the author

Irish, PowerShell MVP, .NET/ASP.NET/SharePoint Developer, Budding Architect. Developer. Montrealer. Opinionated. Montreal, Quebec.

Month List

Page List