Powershell: Event für Progressbar bei Download feuert nicht


Sempervivum

Erfahrenes Mitglied
Ich unternehme gerade erste Schritte mit Powershell und versuche eine Datei von meiner Digitalkamera herunterzuladen. Das funktioniert soweit einwandfrei. Ich möchte jedoch eine Fortschrittsanzeige haben und das Registrieren des Eventhandlers funktioniert leider nicht. Keine Fehleranzeigen, aber er feuert nicht.
Code:
[System.Net.WebClient]$web = new-object System.Net.WebClient

# $wc.DownloadProgressChanged
# $wc.DownloadDataCompleted
# Register-ObjectEvent -InputObject $wc`
# -SourceIdentifier Web.DownloadProgressChanged`
# -EventName DownloadProgressChanged`
# -Action {
#     Write-Host 'fired'
# }

Register-ObjectEvent -InputObject $web -EventName DownloadProgressChanged `
    -SourceIdentifier Web.DownloadProgressChanged -Action {
    Write-Host 'fired'
}
$filename = 'PA110001.ORF'
Write-Host $filename
# Invoke-WebRequest -Uri ('http://192.168.0.10/DCIM/100OLYMP/' + $filename) -OutFile ('d:\temp\' + $filename)
$web.DownloadFile(('http://192.168.0.10/DCIM/100OLYMP/' + $filename), ('d:\temp\' + $filename))
Read-Host -Prompt "Press Enter to exit"
Ich habe mich u. a. hiernach gerichtet:
PowerShell and Events: Object Events
Weiß jemand, woran es liegt?
 

StormChaser

Mitglied
Weiß jemand, woran es liegt?
Ich weiss es leider auch nicht.

Falls es dir aber auf eine Prozentanzeige beim Download ankommt, gibt es ein sehr gutes Script dafür auf stackoverflow:
Slow updates to my event handler from DownloadFileAsync during DownloadProgressChanged event

Das habe ich ausprobiert und ein kurzes Video über den Download einer 2-Gigabyte-Datei angefertigt:

Bei kleinen Dateien geht das so schnell, das man das kaum sieht, daher die 2GB.
 
Zuletzt bearbeitet:

Sempervivum

Erfahrenes Mitglied
Danke für den Hinweis! Das arbeitet auch mit dem WebClient, ich werde es testen.
Das Video lässt sich leider nicht abspielen, YT sagt, dass das Abspielen auf anderen Websites vom Eigentümer deaktiviert wurde :-(
 

Sempervivum

Erfahrenes Mitglied
OK, ich habe mich jetzt etwas weiter damit beschäftigt und mich zunächst mit dem ersten Skript in dem Link auf Stackoverflow beschäftigt. Durch Probieren :( habe ich heraus gefunden, dass es an dieser Anweisung liegt:
Code:
        # optionally wait, but you can break out and it will still write progress
        Wait-Event -SourceIdentifier Finished
Füge ich diese in mein Skript ein, bekomme ich die Ausgaben des Eventhandlers zu Gesicht. So weit so gut, aber ich würde das auch gern verstehen; kann es jemand erklären?

Zweitens habe ich für diese Downloads ein GUI und würde gern den Fortschritt dort in einer Progressbar anzeigen. Kein Problem, diese anzulegen. Ich habe schon gelernt, dass man das Skript in einen Eventhandler legen muss, im einfachsten Fall für das Laden des Formulars. Aber in dem Fall funktioniert zwar der Download, aber die Progressbar wird nicht aktualisiert. Hier das vollständige Testskript:
Code:
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
[System.Windows.Forms.Application]::EnableVisualStyles()
$objForm.Size = New-Object System.Drawing.Size(800, 500)

# Init ProgressBar
$pbrTest = New-Object System.Windows.Forms.ProgressBar
$pbrTest.Maximum = 100
$pbrTest.Minimum = 0
$pbrTest.Location = new-object System.Drawing.Size(10, 10)
$pbrTest.size = new-object System.Drawing.Size(100, 20)
$objForm.Controls.Add($pbrTest)

$objForm.Add_Load( {
        write-host 'after form'
        $pbrTest.Value = 50
        $web = new-object System.Net.WebClient
        Register-ObjectEvent -InputObject $web -EventName DownloadProgressChanged `
            -SourceIdentifier Web.DownloadProgressChanged -Action {
            # $pbrTest.Value = $eventargs.ProgressPercentage
            $pbrTest.Value = 100
            write-host "Percent complete:" $eventargs.ProgressPercentage
        }
        # Register-ObjectEvent -InputObject $web DownloadFileCompleted -SourceIdentifier Finished -Action {
        #     Write-Host 'myfinished'
        # }
        $web.DownloadFileAsync(('die-url'), ('d:\temp\dateiname'))
        # optionally wait, but you can break out and it will still write progress
        # Wait-Event -SourceIdentifier Finished

    })

[void] $objForm.ShowDialog()

Read-Host -Prompt "Press Enter to exit"
 
Zuletzt bearbeitet:

Sempervivum

Erfahrenes Mitglied
Die aktuellen Probleme habe ich jetzt gelöst, und zwar habe ich dies gefunden:
Event Handling & Scope - PowerShell General - Ask the Experts - IDERA Community
Er empfiehlt, statt Register-ObjectEvent add_DownloadFileCompleted zu verwenden, um den Listener zu registrieren. Das löst das Problem, dass der Handler nicht triggerte. Danach hatte ich das Problem, dass die Variable $eventargs nicht verfügbar war, fand jedoch heraus, dass statt dessen $args vorhanden war.
Dieses ist das vollständige Skript:
Code:
$web = new-object System.Net.WebClient

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
[System.Windows.Forms.Application]::EnableVisualStyles()
$objForm.Size = New-Object System.Drawing.Size(800, 500)

# Init ProgressBar
$pbrTest = New-Object System.Windows.Forms.ProgressBar
$pbrTest.Maximum = 100
$pbrTest.Minimum = 0
$pbrTest.Location = new-object System.Drawing.Size(10, 10)
$pbrTest.size = new-object System.Drawing.Size(100, 20)
$objForm.Controls.Add($pbrTest)

$DownloadBtn = New-Object System.Windows.Forms.Button
$DownloadBtn.Location = New-Object System.Drawing.Size(10, 50)
$DownloadBtn.Size = New-Object System.Drawing.Size(100, 20)
$DownloadBtn.Text = "Herunterladen"
$DownloadBtn.Name = "Herunterladen"
$DownloadBtn.Add_Click( {
        $web.add_DownloadProgressChanged( {
                $pbrTest.Value = $args.ProgressPercentage
                Write-Host $args
                Write-Host $eventargs
                write-host "Percent complete:" $args.ProgressPercentage
            })
        # Register-ObjectEvent -InputObject $web DownloadFileCompleted -SourceIdentifier Finished -Action {
        #     Write-Host 'myfinished'
        # }
        $web.DownloadFileAsync(('https://ulrichbangert.de/div/Kormoran-Olympus.jpg'), ('d:\temp\Kormoran-Olympus.jpg'))
    })
$objForm.Controls.Add($DownloadBtn)

[void] $objForm.ShowDialog()

Read-Host -Prompt "Press Enter to exit"