I have created various small scripts and programs to downloading files from the Internet mostly using PHP/cURL and .NET. However, it turns out the easiest way to do this is with PowerShell so I rewrote my .NET application. Here's what the simple version looks like it looks like:
function getfile($url, $filename)
{
$wc = New-Object System.Net.WebClient
try
{
$wc.DownloadFile($url, $filename)
}
catch [System.Net.WebException]
{
Write-Host("Cannot download $url")
}
finally
{
$wc.Dispose()
}
}
To download a file, just specify the URL from which to download and the target location on disk and then call the function like this: $url = "http://msdn.microsoft.com/en-us/library/windows/desktop/aa973757(v=vs.85).aspx"
$filename = "d:\msdn.htm"
getfile $url $filename
The function is quite straightforward. A WebClient object is instantiated and it's DownloadFile method called with the source URL and target path. However, this will cause the function to block and freeze PowerShell console till the file is downloaded. There won't be any kind of download progress notification either. In my original application, I called the DownloadFileAsync method and tracked the progress of the download by handling the DownloadProgressChanged and DownloadFileCompleted events. The same can be accomplished in PowerShell in fewer (albeit more convoluted) lines of code. Here's the asynchronous version of getfile: function getfile($url, $filename)
{
$wc = New-Object System.Net.WebClient
Register-ObjectEvent -InputObject $wc -EventName DownloadProgressChanged -SourceIdentifier WebClient.DownloadProgressChanged -Action { Write-Progress -Activity "Downloading: $($EventArgs.ProgressPercentage)% Completed" -Status $url -PercentComplete $EventArgs.ProgressPercentage; }
Register-ObjectEvent -InputObject $wc -EventName DownloadFileCompleted -SourceIdentifier WebClient.DownloadFileComplete -Action { Write-Host "Download Complete - $filename"; Unregister-Event -SourceIdentifier WebClient.DownloadProgressChanged; Unregister-Event -SourceIdentifier WebClient.DownloadFileComplete; }
try
{
$wc.DownloadFileAsync($url, $filename)
}
catch [System.Net.WebException]
{
Write-Host("Cannot download $url")
}
finally
{
$wc.Dispose()
}
}
The call to DownloadFile has been replaced by DownloadFileAsync. The real difference is in how events are handled. PowerShell registers events individually through the Register-ObjectEvent command. The arguments used in this example are:- InputObject: the source object that raises the events, in this case $wc, the WebClient instance
- EventName: the name of the event, I have used the DownloadProgressChanged and DownloadFileCompleted
- SourceIdentifier: a unique identifier for a particular event registration or subscription. In this example, the SourceIdentifier is used to unregister the events
- Action: a semi-colon delimited list of PowerShell commands that are executed when the event is raised. The Action for DownloadProgressChanged shows a text based progress bar as well as the percentage of download completed using the Write-Progress command. The Action for DownloadFileCompleted completed shows a download complete message and then unregisters both events.