Powershell Progressbar will nicht
Hi @all
auch wenn es mit Write-Progress ein cmdlet gibt würde ich aktuell den Progressbar in der eigenen GUI mit Fortschritt versorgen ohne ein extra Fenster zu haben.
Das endet leider in folgendem Fehler:
Wie krieg ich das aufgelöst, wo wäre der Ansatz?
Gruß
auch wenn es mit Write-Progress ein cmdlet gibt würde ich aktuell den Progressbar in der eigenen GUI mit Fortschritt versorgen ohne ein extra Fenster zu haben.
function robocopy
{
process
{
#count the source files
$filecount = 0
$lb_progressText.text = " Vorbereitung ..."
if ("C:\Quelle" -notlike $null)
{
$sourcefiles = robocopy.exe "C:\Quelle" "C:\Quelle" /L /S /NJH /BYTES /FP /NC /NDL /TS /XJ /R:0 /W:0
If ($sourcefiles[-5] -match '^\s{3}Files\s:\s+(?<Count>\d+).*') { $filecount = $matches.Count }
}
$lb_progressText.Text = $filecount
$lb_progressText.Focus()
$run = robocopy.exe "C:\Quelle" "C:\temp\Ziel" /MIR /ZB /R:10 /W:10 /ETA | foreach
# ab hier scheint er ein Problem zu haben
{
#calculate percentage
$i++
[int]$pct = ($i/$filecount) * 100
#update the progress bar
$pgb_robocopy.Value = ($pct)
$lb_progressText.AppendText($i)
[void] [System.Windows.Forms.Application]::DoEvents()
}
}
end { $pgb_robocopy.Value = 100 }
}
Das endet leider in folgendem Fehler:
ERROR: foreach : Cannot bind parameter 'Process'. Cannot convert the "" value of type "System.String" to type "System.Management.Automation.ScriptBlock".
ERROR:
MainForm.psf (538): ERROR: At Line: 538 char: 91
ERROR: + $run = robocopy.exe "C:\Quelle" "C:\temp\Ziel" /MIR /ZB /R:10 /W:10 /ETA | foreach <<<<
ERROR: + CategoryInfo : InvalidArgument: (:) [ForEach-Object], ParameterBindingException
ERROR: + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.ForEachObjectCommand
ERROR:
Wie krieg ich das aufgelöst, wo wäre der Ansatz?
Gruß
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 285535
Url: https://administrator.de/forum/powershell-progressbar-will-nicht-285535.html
Ausgedruckt am: 16.04.2025 um 10:04 Uhr
15 Kommentare
Neuester Kommentar


Moin,
dein Fehler ist, dass die öffnende geschweifte Klammer bei foreach erst in der nächsten Zeile beginnt, diese muss aber bei Verwendung der Pipe-Schreibweise in der selben Zeile stehen ...
Geht:
geht nicht:
Deswegen auch die Fehlermeldung bezüglich "Skript-Block"
Denn ein {} alleine stehend ist ein Skriptblock.
Gruß jodel32
dein Fehler ist, dass die öffnende geschweifte Klammer bei foreach erst in der nächsten Zeile beginnt, diese muss aber bei Verwendung der Pipe-Schreibweise in der selben Zeile stehen ...
Geht:
| foreach {
| foreach
{
Gruß jodel32

?? Vielleicht mal den Rechner putzen 
Moin zusammen,
Einfaches Beispiel für Robocopy:
Grüße Uwe
Einfaches Beispiel für Robocopy:
#region Import the Assemblies
[reflection.assembly]::loadwithpartialname("System.Windows.Forms") | Out-Null
[reflection.assembly]::loadwithpartialname("System.Drawing") | Out-Null
#endregion
#region Generated Form Objects
$form1 = New-Object System.Windows.Forms.Form
$button1 = New-Object System.Windows.Forms.Button
$progress = New-Object System.Windows.Forms.ProgressBar
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
$timer = New-Object System.Windows.Forms.Timer
#endregion Generated Form Objects
$global:job = $null
$global:currentcnt = 0
$global:totalcnt = 0
$handler_button1_Click= {
if ($button1.Text -eq "Start"){
$timer.Start()
$button1.Text = "Running"
$button1.Enabled = $false
$progress.Value = 0
$global:currentcnt = 0
# Anzahl der Dateien ermitteln
$global:totalcnt = (robocopy "C:\quelle" "C:\ziel" /S /ZB /ETA /L /NS /NC /NJH /NJS /NDL ).length -1
$i = 0
$global:job = Start-Job -ScriptBlock {
robocopy "C:\quelle" "C:\ziel" /S /ZB /ETA /NS /NC /NJH /NJS /NDL /NP /R:10 /W:10
}
}else{
$timer.Stop()
$global:job | stop-job
$global:job | remove-job -Force
$button1.Text = "Start"
}
}
$handler_tick = {
$global:currentcnt += ($global:job | Receive-Job).Count
$percent = ($global:currentcnt / $global:totalcnt) * 100
if ($percent -lt 100) {
$progress.Value = $percent
}else{
$progress.Value = 100
$timer.Enabled = $false
$button1.Enabled = $true
$button1.Text = "Start"
$global:job | remove-job -ErrorAction SilentlyContinue
}
}
$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
$form1.WindowState = $InitialFormWindowState
}
#----------------------------------------------
#region Generated Form Code
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 74
$System_Drawing_Size.Width = 292
$form1.ClientSize = $System_Drawing_Size
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$form1.MaximizeBox = $False
$form1.Name = "form1"
$form1.Text = "ProgressForm"
$button1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 41
$button1.Location = $System_Drawing_Point
$button1.Name = "button1"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 268
$button1.Size = $System_Drawing_Size
$button1.TabIndex = 1
$button1.Text = "Start"
$button1.UseVisualStyleBackColor = $True
$button1.add_Click($handler_button1_Click)
$form1.Controls.Add($button1)
$progress.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 12
$System_Drawing_Point.Y = 12
$progress.Location = $System_Drawing_Point
$progress.Name = "progress"
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Height = 23
$System_Drawing_Size.Width = 268
$progress.Size = $System_Drawing_Size
$progress.TabIndex = 0
$form1.Controls.Add($progress)
#Save the initial state of the form
$InitialFormWindowState = $form1.WindowState
#Init the OnLoad event to correct the initial state of the form
$form1.add_Load($OnLoadForm_StateCorrection)
#Timer settings
$timer.add_tick($handler_tick)
$timer.Enabled = $false
$timer.Interval = 500
#----- Show Form
$form1.ShowDialog() | out-null
# WICHTIG Timer resourcen freigeben
$timer.dispose()
Zitat von @H41mSh1C0R:
Erscheint bei dir auch kurz ein Consolenfester bevor der Kopiervorgang startet?
Nein, das kann schon nicht weil es ja ein Background-Job ist.Erscheint bei dir auch kurz ein Consolenfester bevor der Kopiervorgang startet?
Wenn ich den Log Parameter zum Robocopy hinzufüge läuft der Progressbar nicht los.
Normal, weil mein Skript die Anzahl der Zeilen in der Ausgabe nutzt um den Status zu ermitteln, und bei Verwendung von /LOG:C:\logfile.txt wird die Ausgabe der Dateien unterdrückt deswegen kann der Status nicht ermittelt werden, wenn du die Logging-Option verwenden willst musst du zusätzlich den Parameter /tee verwenden der die kopierten Dateien trotzdem des LOG-Parameters auflistet.Hätte man aber auch selber gesehen wenn man sich die Ausgabe von robocopy mal angesehen hätte
Grüße Uwe

So ein Fenster hab ich hier testweise auch nicht, liegt bestimmt an deiner GUI ...
Background-Job = Keine GUI.
Gruß jodel32
Background-Job = Keine GUI.
Gruß jodel32

Das dispose hab ich im Handler Tick im else Zweig
Keine gute Idee, damit würdest du dir den Event-Handler unter dem Arsch wegziehen Achtung: Wenn dein Skript irgendwie crashed, und er Timer nicht korrekt zerstört wurde macht die ISE hinterher die komischsten Sachen !!!
Teilweise muss man die Maschine dann neu starten, das es wieder läuft.

Sehr wahrscheinlich kommt das Fenster vom ersten ausführen von Robocopy für das Zählen der Files, denn das läuft im Vordergrund-Thread, dann musst du es mit process-start hidden ausführen und die Anzahl der Zeilen abfragen.