0

I'm trying to create a PowerShell script that would download posh-git and then install it automatically. I'd like to have the download happen asynchronously, preferably with the option to have a callback once the download has finished and/or be able to wait for it to complete (but executing code until you want to wait).

I created a function that takes the URL for download, the path where to save it and the callback function. Unfortunately the callback function never seems to be called:

function DownloadFileAsync([string] $url, [string] $destination, [ScriptBlock] $action = $null)
{
    $web_client = New-Object System.Net.WebClient

    if ($action)
    {
        Register-ObjectEvent -InputObject $web_client -EventName DownloadFileCompleted -Action $action | Out-Null
    }

    $web_client.DownloadFileAsync($url, $destination)
}

$download_finished =
{
    # This is never reached
    echo "Download finished"
}

DownloadFileAsync "https://github.com/dahlbyk/posh-git/archive/master.zip" "C:/posh-git-master.zip" $download_finished

How can I fix the callback never being called? Is there also a way to implement a way to wait, later on in the code, for the download to complete?

tambre
  • 4,625
  • 4
  • 42
  • 55
  • `Register-ObjectEvent` behaves weird in function scopes. Try `$web_client.add_DownloadFileCompleted($action)` instead – Mathias R. Jessen Aug 27 '16 at 20:34
  • Do you expect that `echo` will display string on PowerShell host? It is not what `Write-Output` is doing. `echo` -> `Write-Host` – user4003407 Aug 27 '16 at 21:29
  • @MathiasR.Jessen Doing that crashes PowerShell ISE. The problem seems to be instead that I wasn't using Write-Host and the text was never being output to the console. – tambre Aug 28 '16 at 05:45
  • @PetSerAl Could you turn your comment into an answer, as it was the solution. – tambre Aug 28 '16 at 05:45

1 Answers1

6

Output from event action is not printed on PowerShell host, but captured and saved in job, returned by Register-ObjectEvent:

$web_client = New-Object System.Net.WebClient
$Job = Register-ObjectEvent -InputObject $web_client -EventName DownloadStringCompleted -Action {
    Write-Host 'Download completed'
    $EventArgs.Result
}
$web_client.DownloadStringAsync('http://stackoverflow.com/q/39185082')

Now when download completed, you can use Receive-Job $Job to receive job results.

If you want to print something on PowerShell host, then you need to use Write-Host or Out-Host cmdlets.

user4003407
  • 21,204
  • 4
  • 50
  • 60