I want to download files from the Internet on the Form and display the download progress in the ProgressBar. To do this I subscribe to loading events and do asynchronous loading. Everything is working. Here is the simplified code (removed all unnecessary):
Add-Type -assembly System.Windows.Forms
$isDownloaded = $False
$webMain = New-Object System.Net.WebClient
Register-ObjectEvent -InputObject $webMain -EventName 'DownloadFileCompleted' -SourceIdentifier WebMainDownloadFileCompleted -Action {
$Global:isDownloaded = $True
}
Register-ObjectEvent -InputObject $webMain -EventName 'DownloadProgressChanged' -SourceIdentifier WebMainDownloadProgressChanged -Action {
$Global:Data = $event
}
function DownloadFile($Link, $Path, $Name) {
write-host "begin"
$Global:webMain.DownloadFileAsync($Link, $Path)
While (!$isDownloaded) {
$percent = $Global:Data.SourceArgs.ProgressPercentage
If ($percent -ne $null) {
write-host $percent
}
Wait-Event -Timeout 1
}
write-host "end"
}
DownloadFile 'https://www.7-zip.org/a/7z2301-x64.exe' 'D:\7Zip.exe' '7Zip'
Everything is working. Now I add it anywhere in the code
$Form1 = New-Object System.Windows.Forms.Form
or
$Button1 = New-Object System.Windows.Forms.Button
and the script doesn't work. The DownloadProgressChanged and DownloadFileCompleted events do not occur at all.
Question: Why does just creating a Form or Button interfere with the script?
Without System.Windows.Forms.Form the code works, but I will eventually need to create a Form and render the loading on it.
DownloadFileAsync is work - the file is downloaded, but the events in Register-ObjectEvent themselves do not occur when using any New-Object System.Windows.Forms.* (but work great without them).
As stated in comments, PowerShell is not a great language for async programming, the issue is that
.ShowDialog()blocks the thread and is not allowing your events to execute normally. Solution to this is to register the events in a separated runspace, below is as minimal example of how this can be accomplished (as minimal as I could). I have added a few pointer comments to help you understand the logic, though the code is clearly not easy, as stated before, PowerShell is not a language designed for this, C# would give you a much easier time.Demo:
Code: