Benutzer mit den meisten Antworten
Einbiden Progressbar in vorhandenes Script

Frage
-
Hallo zusammen,
ich habe folgendes Script, welches auch soweit ich es sehe, funktioniert. Es kopiert Hörspiele aus einem Verzeichnis auf meinem Rechner auf einen temporär angeschlossenen Mp3 Player. Danach werden die kopierten Hörspiele in ein temporäres Verzeichnis verschoben, um wiederum bei bestehender Netzwerkverbindung auf ein Nas verschoben zu werden.
Dabei wird noch eine Abfrage nach Laufwerksbuchstaben des MP3 Players gemacht, Logfiles angelegt und das ganze durch eine Try Cach Anweisung geschickt.Nun zum Problem:
Da die zum Mp3 Player zu kopierenden Dateien mal ein paar MB und mal ein paar GB betragen, möchte ich gerne eine Progressbar einbauen. (Nur beim kopieren auf den Mp3 Player, nicht bei den weiteren Aktionen).
Das beste und mir verständlichste, was ich dazu im Netz gefunden habe, war folgender Code aus diesem Forum von Denniver:
# Erstelle Fenster $Form1 = New-Object System.Windows.Forms.Form $Form1.ClientSize = "272,78" $Form1.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedToolWindow # Dieser Code wird beim erstmaligen anzeigen des Fensters ausgeführt $Form1.add_Shown({ # Maximum Wert der Fortschrittsanzeige = Anzahl der Files $ProgressBar1.Maximum = $allFiles.length foreach ($file in $allFiles) { $ProgressBar1.PerformStep() # Fortschrittsanzeige um einen Schritt weiter $intSize = $intSize + $file.Length } $Form1.Close() Write-Host "Total size of all files: $intSize bytes." }) # Erstelle Fortschrittsanzeige $ProgressBar1 = New-Object System.Windows.Forms.ProgressBar $ProgressBar1.Location = "12,21" $ProgressBar1.Size = "245,33" $ProgressBar1.Step = 1 # Schrittweite für" .performstep()" $Form1.Controls.Add($ProgressBar1) $allFiles = Get-ChildItem 'C:\Program Files' -recurse # Zeige Fenster $Form1.showdialog()
Nur Leider schaffe ich es nicht, diesen Code in mein Script einzubauen und scheitere immer wieder.
Habt Ihr da eine Idee, an welcher Stelle ich die beiden Scripte zusammen bringen kann?
Bin für jede Hilfe Dankbar!
Sönke
Mein Script:
#################################################################################### # Abfrage Laufwerksbuchstaben aller USB Devices, die "TOSHIBA MK3006GAL USB Device"# # heißen und speichern in einer Variable # #################################################################################### $H320Test = gwmi win32_diskdrive | ?{$_.caption -eq "TOSHIBA MK3006GAL USB Device"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.deviceid} #################### # Variablen setzen # #################### $Quelle = "W:\Hörspiele Temp\PlayerKopieren\*" $Temp = "W:\Hörspiele Temp\MediaKopieren\" $Temp2 = "W:\Hörspiele Temp\MediaKopieren\*" $Media = "\\MEDIA\Multimedia\Audio\Hoerspiele\Sortieren\" $MovedFilesMedia = "C:\temp\Logs\MP3Player\MovedFilesMedia.txt" $MovedFilesMp3 = "C:\temp\Logs\MP3Player\MovedFilesMp3.txt" $ScriptErrorsMedia = "C:\temp\Logs\MP3Player\ScriptErrorsMedia.txt" $ScriptErrorsMp3 = "C:\temp\Logs\MP3Player\ScriptErrorsMp3.txt" ##################################################################################### # Setzt Laufwerksbuchstaben des USB MP3 Players und Pfad zu Hörspielen zusammen. # # Falls nicht vorhanden, Exit! # ##################################################################################### Try { $H320 = "$H320Test\Music\Hörspiele" gci $H320 -ErrorAction stop } catch {$time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler! Vermutlich MP3 Player nicht angeschlossen, daher Pfad falsch: "+$_.exception.message,$time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf MP3 Player zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { Copy-Item -Path $Quelle -Destination $H320 -container -force -recurse -ErrorAction Stop Get-ChildItem -Recurse $Quelle | ForEach-Object { $FilePath = $_.fullname, $_.Lastaccesstime $filepath | Out-file -Append $MovedFilesMp3} move-Item -Path $Quelle -Destination $Temp -ErrorAction Stop cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf NAS zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { Copy-Item -Path $Temp2 -Destination $Media -container -force -recurse -ErrorAction Stop Get-ChildItem -Recurse $temp2 | ForEach-Object { $FilePath2 = $_.fullname, $_.Lastaccesstime $filepath2 | Out-file -Append $MovedFilesMedia} remove-Item -Path $temp2 -recurse -ErrorAction Stop cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMedia ("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFehler.vbs" }
- Bearbeitet Sönke T Montag, 7. Januar 2013 13:58 Erneut falsche Formatierung des Scriptes
Antworten
-
Da Write-Progress langsamer sein soll
Wer behauptet das und warum? Kann ich nicht bestätigen!
Wenn du mit Copy-Item "c:\temp\*" Dateien Kopierst, dann kannst du natürlich keinen Progress sehen da Copy-Item die Dateien Intern verarbeitet.
Wenn du Progress Pro Datei sehen willst musst du mit Get-ChildItem | ForEach | Copy-Item Arbeiten, um jede Datei einzeln zu sehen.Ich habe schon sehr viel Erfahrung mit Progress gemacht.
Die erste Erfahrung ist die, dass das Problem viel einfacher aussieht als es ist!
In dem Beispiel von Denniver z.B. werden erst alle Dateien mit "Get-ChildItem 'C:\Program Files' -recurse" geholt, erst dann ist die Anzahl der Dateien bekannt ($allFiles = Maximalwert des Balkens) und der Progress-Balken kann Korrekt Berechnet und dargestellt werden.
Der große Pferdefuß bei dieser Vorgehensweise ist, dass es sehr lange dauert die Anzahl der Dateien zu ermitteln. Das Progress-Fenster müsste also schon dort im Get-ChildItem erscheinen!
(ändere den Pfad in Dennivers code mal auf C:\ "Get-ChildItem 'C:\' -recurse" ;-))
Bei einem Kopiervorgang mit sehr vielen Dateien den Maximalwert (Anzahl der Dateien) im Voraus zu ermitteln, kostet also wiederum viel Zeit!
Das Ermitteln des Endwertes ist zu teuer!
Eine Progress-Bar bei der man nicht den Anfangs- und Endwert kennt, macht aber keinen Sinn!
Hier wird dann meist einen dumme Progress-Bar dargestellt, die einfach nur als Beruhigungs-Animation für den User ist (das das Programm nicht eingefroren ist).
Deine Beste Wahl ist hier wirklich das Einfache darstellen von den Dateinamen!
Get-ChildItem | ForEach | Copy-Item
Kopiere Datei: Hörspiel_1.mp3 …
Kopiere Datei: Hörspiel_2.mp3 …
Kopiere Datei: Hörspiel_3.mp3 …
Kopiere Datei: Hörspiel_4.mp3 …Du sagst dass die Dateien sehr groß sind. Das Kopieren einer Datei dauert sehr lange!?
Deshalb wäre hier der Fortschritt beim Kopieren INNERHALB einer Datei viel interessanter!?
Hier kann man den Byte-Fortschritt leicht darstellen, da die Größe einer Datei (Maximalwert) leicht zu ermitteln ist!
Versuch mal folgenden Code mit Dateien die du nicht mehr brauchst ;-)) :Function Copy-FileProgress { <# .SYNOPSIS Copies Files from a Source Path to a Destination Path but with Progress in 1MB steps .DESCRIPTION Set-ServicePassword changes the Password for a AD User which is used in Services. The script first change the Password in AD, then connect to the remote Machine with a PSSession and changes the Service Startup Accounts Password .PARAMETER Path Source Path of File .PARAMETER Destination Destination Path of File .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\test.txt' .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\New-test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\New-test.txt' Destination File gets a new Name! .Note Author: Peter Kriegel 08.January.2013 #> [CMDletBinding()] param( [Parameter(Mandatory=$True,Position=0, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Path, [Parameter(Mandatory=$True,Position=1, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Destination ) Process { Try { $ffile = [io.file]::OpenRead($Path) } Catch { $ffile.Close() Write-Error $Error[0] Return } Try { $tofile = [io.file]::OpenWrite($Destination ) } Catch { $ffile.Close() $tofile.Close() Write-Error $Error[0] Return } Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete 0 try { [byte[]]$buff = new-object byte[] 4096 [long]$total = [long]$count = 0 do { $count = $ffile.Read($buff, 0, $buff.Length) $tofile.Write($buff, 0, $count) $total += $count if ($total % 1mb -eq 0) { if($ffile.Length -gt 0) { Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete ([int]($total/$ffile.Length* 100)) -CurrentOperation "$([long]($total/1mb))MB from $([long]($ffile.Length/1mb))MB" } } } while ($count -gt 0) } finally { $ffile.Close() $tofile.Close() } } # end process } # end function #################################################################################### # Abfrage Laufwerksbuchstaben aller USB Devices, die "TOSHIBA MK3006GAL USB Device"# # heißen und speichern in einer Variable # #################################################################################### $H320Test = gwmi win32_diskdrive | ?{$_.caption -eq "TOSHIBA MK3006GAL USB Device"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.deviceid} #################### # Variablen setzen # #################### $Quelle = "W:\Hörspiele Temp\PlayerKopieren\*" $Temp = "W:\Hörspiele Temp\MediaKopieren\" $Temp2 = "W:\Hörspiele Temp\MediaKopieren\*" $Media = "\\MEDIA\Multimedia\Audio\Hoerspiele\Sortieren\" $MovedFilesMedia = "C:\temp\Logs\MP3Player\MovedFilesMedia.txt" $MovedFilesMp3 = "C:\temp\Logs\MP3Player\MovedFilesMp3.txt" $ScriptErrorsMedia = "C:\temp\Logs\MP3Player\ScriptErrorsMedia.txt" $ScriptErrorsMp3 = "C:\temp\Logs\MP3Player\ScriptErrorsMp3.txt" ##################################################################################### # Setzt Laufwerksbuchstaben des USB MP3 Players und Pfad zu Hörspielen zusammen. # # Falls nicht vorhanden, Exit! # ##################################################################################### Try { $H320 = "$H320Test\Music\Hörspiele" gci $H320 -ErrorAction stop } catch {$time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler! Vermutlich MP3 Player nicht angeschlossen, daher Pfad falsch: "+$_.exception.message,$time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf MP3 Player zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { # Stern vom ende des Pfades entfernen wenn vorhanden If($Quelle.substring($Quelle.length -1 ,1) -eq '*'){ $nQuelle = $Quelle.remove($Quelle.length - 1) } Else { $nQuelle = $Quelle } $FolderList = @() # Ordnerstruktur und Dateien Moven (Kopieren und von der Quelle löschen) Get-ChildItem $nQuelle -Recurse | ForEach-Object { # Ziel Pfad zusammen bauen; in dem der Textteil vom Quellpfad und Zielpfad ausgetauscht ist $nZiel = (Join-Path $H320 ($_.Fullname.replace($nQuelle,''))) If($_.PSIsContainer){ # Verzeichnisse bearbeiten (ordnerstruktur anlegen) # Neuen Pfad zusammenbauen und neues (Unter-)Verzeichnis im Ziel anlegen New-Item -Path $nZiel -ItemType directory -Force -ErrorAction Stop | Out-Null $FolderList += $_.Fullname } # end IF Else { # Datei mit Progress kopieren und danach löschen (Move) Copy-FileProgress -Path $_.Fullname -Destination $nZiel -ErrorAction Stop # Erfolgreich Kopierte Dateien von Quelle löschen Remove-Item -Path $_.Fullname -Force -ErrorAction Stop | Out-Null # Logfile schreiben @($_.fullname, $_.Lastaccesstime) | Out-file -Append $MovedFilesMp3 } # end Else } # end ForEach # Leere zurückgebliebene Ordner löschen $FolderList | Sort-Object -Descending | ForEach-Object { # Wenn der Ordner Leer ist löschen If(@(Get-ChildItem $_).count -eq 0) { Remove-Item $_ -Force | Out-Null } } cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf NAS zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { Copy-Item -Path $Temp2 -Destination $Media -container -force -recurse -ErrorAction Stop Get-ChildItem -Recurse $temp2 | ForEach-Object { $FilePath2 = $_.fullname, $_.Lastaccesstime $filepath2 | Out-file -Append $MovedFilesMedia} remove-Item -Path $temp2 -recurse -ErrorAction Stop cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMedia ("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFehler.vbs" }
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!
- Als Antwort markiert Sönke T Dienstag, 8. Januar 2013 18:48
- Bearbeitet Peter Kriegel Mittwoch, 9. Januar 2013 07:24
-
Zu 1. Wenn Denniver das so sagt dann ist das auch so in der Konsole! Ich habe hier in der ISE gearbeitet da ist das schnell.
Lass uns erstmal mit Write-Progress weitermachen! Wenn das Funktioniert mache ich noch einen WinForms Version von dem Script.Zu 2. Das 'Flache' Kopieren von Dateien die Direkt in einem Ordner liegen ist in der PowerShell recht einfach und geht (Ungefähr) so :
$Quelle1 = "C:\temp\*" $Ziel1 = "D:\temp\test" # Pipeline nutzen mit ForEach-Object Cmdlet! # Wir nutzen NICHT den -recurse Parameter, da wir nur die 1. Ebene Kopieren (Dateien direkt im Ordner) Get-ChildItem $Quelle1 | ForEach-Object { # $_ ist das Objekt das gerade in der Pipeline verarbeitet wird # Wir kopieren nur Dateien, keine Ordner! If(-not ($_.PSIsContainer)){ # Das Ziel des kopiervorganges setzt sich zusammen aud dem ZielPfad und # dem Namen der zu kopierenden Datei $NeuesZiel = Join-Path $Ziel1 $_.Name # Anzeigen des kopiervorganges Write-Host "Ich Kopiere $($_.Fullname) nach $NeuesZiel" # Kopieren der Datei Copy-Item $_.Fullname $NeuesZiel -force } # Ende von IF } # Ende von ForEach-Object
Es gibt in der PowerShell 2 Verschieden ForEach ! Da musst du aufpassen! Einmal das ForEach-Object { ... } Cmdlet und die ForEach ($File in Files) { ... } Schleife ! Gemeinerweise hat das ForEach-Object { ... } Cmdlet einen Alias der ForEach { ... } heisst! Da kommt man schnell durcheinander! Der unterschied ist das ForEach-Object { ... } Cmdlet wird in der Pipeline eingesetzt und die ForEach ($File in Files) { ... } Schleife nicht!
Ich habe das Script oben nochmal Berichtigt es enthielt noch einen klitzekleinen Fehler.
Der gesamte Code von mir ist ein einziges script!
Funktionen muss man VOR den eigentlichen Code schreiben, damit PowerShell die Funktion erst kennt BEVOR Sie genutzt wird. (Eine Funktion wird erst deklariert dann kann sie mehrmals im Code aufgerufen werden)
Bitte Kopiere das gesamte Script in eine .PS1 Datei oder die PowerShell ISE und probiere es noch einmal aus.
>>>> Deinen Anpassungen meines scriptes zufolge werden die Dateien verschoben, nicht kopiert. Das darf nicht sein...
Das habe ich Falsch verstanden! Hier eine Version OHNE Löschvorgänge (Ungetestet!):
Function Copy-FileProgress { <# .SYNOPSIS Copies Files from a Source Path to a Destination Path but with Progress in 1MB steps .DESCRIPTION Set-ServicePassword changes the Password for a AD User which is used in Services. The script first change the Password in AD, then connect to the remote Machine with a PSSession and changes the Service Startup Accounts Password .PARAMETER Path Source Path of File .PARAMETER Destination Destination Path of File .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\test.txt' .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\New-test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\New-test.txt' Destination File gets a new Name! .Note Author: Peter Kriegel 08.January.2013 #> [CMDletBinding()] param( [Parameter(Mandatory=$True,Position=0, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Path, [Parameter(Mandatory=$True,Position=1, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Destination ) Process { Try { $ffile = [io.file]::OpenRead($Path) } Catch { $ffile.Close() Write-Error $Error[0] Return } Try { $tofile = [io.file]::OpenWrite($Destination ) } Catch { $ffile.Close() $tofile.Close() Write-Error $Error[0] Return } Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete 0 try { [byte[]]$buff = new-object byte[] 4096 [long]$total = [long]$count = 0 do { $count = $ffile.Read($buff, 0, $buff.Length) $tofile.Write($buff, 0, $count) $total += $count if ($total % 1mb -eq 0) { if($ffile.Length -gt 0) { Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete ([int]($total/$ffile.Length* 100)) -CurrentOperation "$([long]($total/1mb))MB from $([long]($ffile.Length/1mb))MB" } } } while ($count -gt 0) } finally { $ffile.Close() $tofile.Close() } } # end process } # end function #################################################################################### # Abfrage Laufwerksbuchstaben aller USB Devices, die "TOSHIBA MK3006GAL USB Device"# # heißen und speichern in einer Variable # #################################################################################### $H320Test = gwmi win32_diskdrive | ?{$_.caption -eq "TOSHIBA MK3006GAL USB Device"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.deviceid} #################### # Variablen setzen # #################### $Quelle = "W:\Hörspiele Temp\PlayerKopieren\*" $Temp = "W:\Hörspiele Temp\MediaKopieren\" $Temp2 = "W:\Hörspiele Temp\MediaKopieren\*" $Media = "\\MEDIA\Multimedia\Audio\Hoerspiele\Sortieren\" $MovedFilesMedia = "C:\temp\Logs\MP3Player\MovedFilesMedia.txt" $MovedFilesMp3 = "C:\temp\Logs\MP3Player\MovedFilesMp3.txt" $ScriptErrorsMedia = "C:\temp\Logs\MP3Player\ScriptErrorsMedia.txt" $ScriptErrorsMp3 = "C:\temp\Logs\MP3Player\ScriptErrorsMp3.txt" ##################################################################################### # Setzt Laufwerksbuchstaben des USB MP3 Players und Pfad zu Hörspielen zusammen. # # Falls nicht vorhanden, Exit! # ##################################################################################### Try { $H320 = "$H320Test\Music\Hörspiele" gci $H320 -ErrorAction stop } catch {$time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler! Vermutlich MP3 Player nicht angeschlossen, daher Pfad falsch: "+$_.exception.message,$time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf MP3 Player zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { # Stern vom ende des Pfades entfernen wenn vorhanden If($Quelle.substring($Quelle.length -1 ,1) -eq '*'){ $nQuelle = $Quelle.remove($Quelle.length - 1) } Else { $nQuelle = $Quelle } # Ordnerstruktur und Dateien Kopieren Get-ChildItem $nQuelle -Recurse | ForEach-Object { # Ziel Pfad zusammen bauen; in dem der Textteil vom Quellpfad und Zielpfad ausgetauscht ist $nZiel = (Join-Path $H320 ($_.Fullname.replace($nQuelle,''))) If($_.PSIsContainer){ # Verzeichnisse bearbeiten (ordnerstruktur anlegen) # Neuen Pfad zusammenbauen und neues (Unter-)Verzeichnis im Ziel anlegen New-Item -Path $nZiel -ItemType directory -Force -ErrorAction Stop | Out-Null } # end IF Else { # Datei mit Progress kopieren Copy-FileProgress -Path $_.Fullname -Destination $nZiel -ErrorAction Stop # Logfile schreiben @($_.fullname, $_.Lastaccesstime) | Out-file -Append $MovedFilesMp3 } # end Else } # end ForEach cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf NAS zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { Copy-Item -Path $Temp2 -Destination $Media -container -force -recurse -ErrorAction Stop Get-ChildItem -Recurse $temp2 | ForEach-Object { $FilePath2 = $_.fullname, $_.Lastaccesstime $filepath2 | Out-file -Append $MovedFilesMedia} remove-Item -Path $temp2 -recurse -ErrorAction Stop cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMedia ("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFehler.vbs" }
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Mittwoch, 9. Januar 2013 08:14
- Als Antwort markiert Sönke T Donnerstag, 10. Januar 2013 08:18
Alle Antworten
-
Reicht nicht das Cmdlet Write-Progress?
Get-Help Write-Progress -full
Wo genau ist die stelle in deinem Script, wo du den Progress sehen willst? (Bitte mit Kommentar markieren)
Möchtest du eine Zähler pro Datei ? Dies ist auch Leicht möglich durch die Anzeige einer Textmeldung z.B.: "Kopieren von Datei Hörspiel3.mp3"
Oder möchtest du den Progress beim Kopieren der Bytes einer Datei sehen? Schwerer mit .Net Streams zu realisieren!
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Montag, 7. Januar 2013 15:03
-
Hallo,
Write-Progress war mein erster Versuch der ebenfalls scheiterte. Da Write-Progress langsamer sein soll, habe ich mich für WindowsForms entschieden. Wäre zwar meine erste Wahl, wenn es aber nicht einfach realisieren ist, dann auch mit Write Progress. (Wenn dabei nicht beim Kopieren von 2 -3 GB ein signifikanter Unterschied festzustellen ist). Ein Zähler pro Datei wäre schön, noch besser eine Prozent oder Zeitanzeige, damit ungefähr die verbleibenden Zeit eingeschätzt werden kann. (Möchte gleich für spätere Scripte daraus lernen). Die Bytes muss ich nicht umbedingt sehen.
Hier die Stelle, an der der Kopiervorgang startet:
################################################ # Versucht Hörspiele auf MP3 Player zu kopieren. Logfiles # werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang #scheitert, Exit! # ################################################# try { Copy-Item -Path $Quelle -Destination $H320 -container -force -recurse -ErrorAction Stop # Hier soll die Progressbar starten.
Danke für eure Hilfe...
-
Da Write-Progress langsamer sein soll
Wer behauptet das und warum? Kann ich nicht bestätigen!
Wenn du mit Copy-Item "c:\temp\*" Dateien Kopierst, dann kannst du natürlich keinen Progress sehen da Copy-Item die Dateien Intern verarbeitet.
Wenn du Progress Pro Datei sehen willst musst du mit Get-ChildItem | ForEach | Copy-Item Arbeiten, um jede Datei einzeln zu sehen.Ich habe schon sehr viel Erfahrung mit Progress gemacht.
Die erste Erfahrung ist die, dass das Problem viel einfacher aussieht als es ist!
In dem Beispiel von Denniver z.B. werden erst alle Dateien mit "Get-ChildItem 'C:\Program Files' -recurse" geholt, erst dann ist die Anzahl der Dateien bekannt ($allFiles = Maximalwert des Balkens) und der Progress-Balken kann Korrekt Berechnet und dargestellt werden.
Der große Pferdefuß bei dieser Vorgehensweise ist, dass es sehr lange dauert die Anzahl der Dateien zu ermitteln. Das Progress-Fenster müsste also schon dort im Get-ChildItem erscheinen!
(ändere den Pfad in Dennivers code mal auf C:\ "Get-ChildItem 'C:\' -recurse" ;-))
Bei einem Kopiervorgang mit sehr vielen Dateien den Maximalwert (Anzahl der Dateien) im Voraus zu ermitteln, kostet also wiederum viel Zeit!
Das Ermitteln des Endwertes ist zu teuer!
Eine Progress-Bar bei der man nicht den Anfangs- und Endwert kennt, macht aber keinen Sinn!
Hier wird dann meist einen dumme Progress-Bar dargestellt, die einfach nur als Beruhigungs-Animation für den User ist (das das Programm nicht eingefroren ist).
Deine Beste Wahl ist hier wirklich das Einfache darstellen von den Dateinamen!
Get-ChildItem | ForEach | Copy-Item
Kopiere Datei: Hörspiel_1.mp3 …
Kopiere Datei: Hörspiel_2.mp3 …
Kopiere Datei: Hörspiel_3.mp3 …
Kopiere Datei: Hörspiel_4.mp3 …Du sagst dass die Dateien sehr groß sind. Das Kopieren einer Datei dauert sehr lange!?
Deshalb wäre hier der Fortschritt beim Kopieren INNERHALB einer Datei viel interessanter!?
Hier kann man den Byte-Fortschritt leicht darstellen, da die Größe einer Datei (Maximalwert) leicht zu ermitteln ist!
Versuch mal folgenden Code mit Dateien die du nicht mehr brauchst ;-)) :Function Copy-FileProgress { <# .SYNOPSIS Copies Files from a Source Path to a Destination Path but with Progress in 1MB steps .DESCRIPTION Set-ServicePassword changes the Password for a AD User which is used in Services. The script first change the Password in AD, then connect to the remote Machine with a PSSession and changes the Service Startup Accounts Password .PARAMETER Path Source Path of File .PARAMETER Destination Destination Path of File .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\test.txt' .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\New-test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\New-test.txt' Destination File gets a new Name! .Note Author: Peter Kriegel 08.January.2013 #> [CMDletBinding()] param( [Parameter(Mandatory=$True,Position=0, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Path, [Parameter(Mandatory=$True,Position=1, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Destination ) Process { Try { $ffile = [io.file]::OpenRead($Path) } Catch { $ffile.Close() Write-Error $Error[0] Return } Try { $tofile = [io.file]::OpenWrite($Destination ) } Catch { $ffile.Close() $tofile.Close() Write-Error $Error[0] Return } Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete 0 try { [byte[]]$buff = new-object byte[] 4096 [long]$total = [long]$count = 0 do { $count = $ffile.Read($buff, 0, $buff.Length) $tofile.Write($buff, 0, $count) $total += $count if ($total % 1mb -eq 0) { if($ffile.Length -gt 0) { Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete ([int]($total/$ffile.Length* 100)) -CurrentOperation "$([long]($total/1mb))MB from $([long]($ffile.Length/1mb))MB" } } } while ($count -gt 0) } finally { $ffile.Close() $tofile.Close() } } # end process } # end function #################################################################################### # Abfrage Laufwerksbuchstaben aller USB Devices, die "TOSHIBA MK3006GAL USB Device"# # heißen und speichern in einer Variable # #################################################################################### $H320Test = gwmi win32_diskdrive | ?{$_.caption -eq "TOSHIBA MK3006GAL USB Device"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.deviceid} #################### # Variablen setzen # #################### $Quelle = "W:\Hörspiele Temp\PlayerKopieren\*" $Temp = "W:\Hörspiele Temp\MediaKopieren\" $Temp2 = "W:\Hörspiele Temp\MediaKopieren\*" $Media = "\\MEDIA\Multimedia\Audio\Hoerspiele\Sortieren\" $MovedFilesMedia = "C:\temp\Logs\MP3Player\MovedFilesMedia.txt" $MovedFilesMp3 = "C:\temp\Logs\MP3Player\MovedFilesMp3.txt" $ScriptErrorsMedia = "C:\temp\Logs\MP3Player\ScriptErrorsMedia.txt" $ScriptErrorsMp3 = "C:\temp\Logs\MP3Player\ScriptErrorsMp3.txt" ##################################################################################### # Setzt Laufwerksbuchstaben des USB MP3 Players und Pfad zu Hörspielen zusammen. # # Falls nicht vorhanden, Exit! # ##################################################################################### Try { $H320 = "$H320Test\Music\Hörspiele" gci $H320 -ErrorAction stop } catch {$time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler! Vermutlich MP3 Player nicht angeschlossen, daher Pfad falsch: "+$_.exception.message,$time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf MP3 Player zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { # Stern vom ende des Pfades entfernen wenn vorhanden If($Quelle.substring($Quelle.length -1 ,1) -eq '*'){ $nQuelle = $Quelle.remove($Quelle.length - 1) } Else { $nQuelle = $Quelle } $FolderList = @() # Ordnerstruktur und Dateien Moven (Kopieren und von der Quelle löschen) Get-ChildItem $nQuelle -Recurse | ForEach-Object { # Ziel Pfad zusammen bauen; in dem der Textteil vom Quellpfad und Zielpfad ausgetauscht ist $nZiel = (Join-Path $H320 ($_.Fullname.replace($nQuelle,''))) If($_.PSIsContainer){ # Verzeichnisse bearbeiten (ordnerstruktur anlegen) # Neuen Pfad zusammenbauen und neues (Unter-)Verzeichnis im Ziel anlegen New-Item -Path $nZiel -ItemType directory -Force -ErrorAction Stop | Out-Null $FolderList += $_.Fullname } # end IF Else { # Datei mit Progress kopieren und danach löschen (Move) Copy-FileProgress -Path $_.Fullname -Destination $nZiel -ErrorAction Stop # Erfolgreich Kopierte Dateien von Quelle löschen Remove-Item -Path $_.Fullname -Force -ErrorAction Stop | Out-Null # Logfile schreiben @($_.fullname, $_.Lastaccesstime) | Out-file -Append $MovedFilesMp3 } # end Else } # end ForEach # Leere zurückgebliebene Ordner löschen $FolderList | Sort-Object -Descending | ForEach-Object { # Wenn der Ordner Leer ist löschen If(@(Get-ChildItem $_).count -eq 0) { Remove-Item $_ -Force | Out-Null } } cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf NAS zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { Copy-Item -Path $Temp2 -Destination $Media -container -force -recurse -ErrorAction Stop Get-ChildItem -Recurse $temp2 | ForEach-Object { $FilePath2 = $_.fullname, $_.Lastaccesstime $filepath2 | Out-file -Append $MovedFilesMedia} remove-Item -Path $temp2 -recurse -ErrorAction Stop cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMedia ("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFehler.vbs" }
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!
- Als Antwort markiert Sönke T Dienstag, 8. Januar 2013 18:48
- Bearbeitet Peter Kriegel Mittwoch, 9. Januar 2013 07:24
-
Hallo,
erst mal danke für die ausführliche Antwort!
1. zu "Wer behauptet das und warum? Kann ich nicht bestätigen!"
dort sagt er " Wichtig ist aber zu beachten, das alle Fortschrittsanzeigen deinen Code deutlich verlangsamen. Write-Progress in der Console ist da besonders heftig.Wenn du eine "richtige", d.h. grafische Fortschrittsanzeige möchtest, musst du Winforms benutzen, was etwas komplizierter-, aber auch schneller als Write-Progress ist."
2. zu "Get-ChildItem | ForEach | Copy-Item
Kopiere Datei: Hörspiel_1.mp3 …
Kopiere Datei: Hörspiel_2.mp3 …
Kopiere Datei: Hörspiel_3.mp3 …
Kopiere Datei: Hörspiel_4.mp3 …"Ich glaube, so sollte ich es machen, da ich als Anfänger (Bin froh, dass ich mein eigenes script noch verstehe) durch deine script nicht durchsteige und es nicht funktionierte. (Vermutlich da ich nicht mal weiß wo ich die Pfade anpassen muss und ob dein Codeblock nun ein script ist oder die Function für sich alleine steht).
Mit dem einfachsten Weg lerne ich da vermutlich auch am meisten.
Nur wie sieht das mit Get-ChildItem | ForEach | Copy-Item in meinem Script aus? Ist das etwa so gemeint?
$Quelle1 = "C:\temp\Hörspiele\*" $Ziel1 = "c:\temp\Logs" gci $Quelle1 -recurse foreach ($File in $Quelle1) {copy-item $File $ziel1 -force}
3. zu "Du sagst dass die Dateien sehr groß sind. Das Kopieren einer Datei dauert sehr lange!?
Deshalb wäre hier der Fortschritt beim Kopieren INNERHALB einer Datei viel interessanter!?Hier habe ich mich nicht deutlich genug ausgedrückt: Mal sind im Quellverzeichnis z.B. zwei Hörspiel Verzeichnisse mit jweils ca 10 Dateien a 8 MB. Macht 160 MB, kopieren geht recht schnell. Manchmal ist dort auch ein größeres Hörbuchverzeichnis mit diversen Unterverzeichnissen. Hier sind die Dateien auch meistens nur bis 8 MB groß, nur sind es so viele, das dort auch mal 1-2 GB zusammen kommen. Teilweise sind die Dateien auch 50-100 MB groß, aber nicht größer.
Da ich das script mit einer Verknüpfung vom Desktop starte ( mit dem Aufruf C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "& 'C:\Program Files\Scripte\Andere Scripte\MP3Player\MP3Player.ps1'" bekomme ich während des kopierens nichts mit.
Eine "Beruhigungs-Animation" möchte ich nicht, also entweder die einfachste Variante der Progressbar oder eben Get-ChildItem | ForEach | Copy-Item.
Zu deinem Scriptblock:
1. Einfaches Kopie und Paste des scriptes im ganzen hat nicht funktioniert.
2. Ist das überhaupt ein script oder sind das zwei? (Der Block der Function, von dem ich nicht mal verstehe wo ich evtl. Pfade anpassen muss).
3. Deinen Anpassungen meines scriptes zufolge werden die Dateien verschoben, nicht kopiert. Das darf nicht sein, da die Dateien im ersten Schritt nur auf den MP3 Player kopier werden sollen. Nur wenn das erfolgreich war, sollen die Datein in ein Temporäres Verzeichnis verschoben werden. Hierfür brauch ich aber auch schon keine Anzeige mehr. Eine Anzeige ist nur für den Kopiervorgang auf den MP3 Player nötig.Also bei:
try { Copy-Item -Path $Quelle -Destination $H320 -container -force -recurse -ErrorAction Stop # Hier soll die Progressbar starten und zwar nur für diesen Copy Vorgang!)
Nochmals danke für deine Mühe!
-
Zu 1. Wenn Denniver das so sagt dann ist das auch so in der Konsole! Ich habe hier in der ISE gearbeitet da ist das schnell.
Lass uns erstmal mit Write-Progress weitermachen! Wenn das Funktioniert mache ich noch einen WinForms Version von dem Script.Zu 2. Das 'Flache' Kopieren von Dateien die Direkt in einem Ordner liegen ist in der PowerShell recht einfach und geht (Ungefähr) so :
$Quelle1 = "C:\temp\*" $Ziel1 = "D:\temp\test" # Pipeline nutzen mit ForEach-Object Cmdlet! # Wir nutzen NICHT den -recurse Parameter, da wir nur die 1. Ebene Kopieren (Dateien direkt im Ordner) Get-ChildItem $Quelle1 | ForEach-Object { # $_ ist das Objekt das gerade in der Pipeline verarbeitet wird # Wir kopieren nur Dateien, keine Ordner! If(-not ($_.PSIsContainer)){ # Das Ziel des kopiervorganges setzt sich zusammen aud dem ZielPfad und # dem Namen der zu kopierenden Datei $NeuesZiel = Join-Path $Ziel1 $_.Name # Anzeigen des kopiervorganges Write-Host "Ich Kopiere $($_.Fullname) nach $NeuesZiel" # Kopieren der Datei Copy-Item $_.Fullname $NeuesZiel -force } # Ende von IF } # Ende von ForEach-Object
Es gibt in der PowerShell 2 Verschieden ForEach ! Da musst du aufpassen! Einmal das ForEach-Object { ... } Cmdlet und die ForEach ($File in Files) { ... } Schleife ! Gemeinerweise hat das ForEach-Object { ... } Cmdlet einen Alias der ForEach { ... } heisst! Da kommt man schnell durcheinander! Der unterschied ist das ForEach-Object { ... } Cmdlet wird in der Pipeline eingesetzt und die ForEach ($File in Files) { ... } Schleife nicht!
Ich habe das Script oben nochmal Berichtigt es enthielt noch einen klitzekleinen Fehler.
Der gesamte Code von mir ist ein einziges script!
Funktionen muss man VOR den eigentlichen Code schreiben, damit PowerShell die Funktion erst kennt BEVOR Sie genutzt wird. (Eine Funktion wird erst deklariert dann kann sie mehrmals im Code aufgerufen werden)
Bitte Kopiere das gesamte Script in eine .PS1 Datei oder die PowerShell ISE und probiere es noch einmal aus.
>>>> Deinen Anpassungen meines scriptes zufolge werden die Dateien verschoben, nicht kopiert. Das darf nicht sein...
Das habe ich Falsch verstanden! Hier eine Version OHNE Löschvorgänge (Ungetestet!):
Function Copy-FileProgress { <# .SYNOPSIS Copies Files from a Source Path to a Destination Path but with Progress in 1MB steps .DESCRIPTION Set-ServicePassword changes the Password for a AD User which is used in Services. The script first change the Password in AD, then connect to the remote Machine with a PSSession and changes the Service Startup Accounts Password .PARAMETER Path Source Path of File .PARAMETER Destination Destination Path of File .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\test.txt' .EXAMPLE Copy-File -Path 'C:\Temp\test.txt' -Destination 'D:\temp\New-test.txt' Copies the File from 'C:\Temp\test.txt' to 'D:\temp\New-test.txt' Destination File gets a new Name! .Note Author: Peter Kriegel 08.January.2013 #> [CMDletBinding()] param( [Parameter(Mandatory=$True,Position=0, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Path, [Parameter(Mandatory=$True,Position=1, ValueFromPipeline=$True, ValueFromPipelineByPropertyName=$True)] [string]$Destination ) Process { Try { $ffile = [io.file]::OpenRead($Path) } Catch { $ffile.Close() Write-Error $Error[0] Return } Try { $tofile = [io.file]::OpenWrite($Destination ) } Catch { $ffile.Close() $tofile.Close() Write-Error $Error[0] Return } Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete 0 try { [byte[]]$buff = new-object byte[] 4096 [long]$total = [long]$count = 0 do { $count = $ffile.Read($buff, 0, $buff.Length) $tofile.Write($buff, 0, $count) $total += $count if ($total % 1mb -eq 0) { if($ffile.Length -gt 0) { Write-Progress -Activity "Copying file" -status "$Path -> $Destination " -PercentComplete ([int]($total/$ffile.Length* 100)) -CurrentOperation "$([long]($total/1mb))MB from $([long]($ffile.Length/1mb))MB" } } } while ($count -gt 0) } finally { $ffile.Close() $tofile.Close() } } # end process } # end function #################################################################################### # Abfrage Laufwerksbuchstaben aller USB Devices, die "TOSHIBA MK3006GAL USB Device"# # heißen und speichern in einer Variable # #################################################################################### $H320Test = gwmi win32_diskdrive | ?{$_.caption -eq "TOSHIBA MK3006GAL USB Device"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_.deviceid} #################### # Variablen setzen # #################### $Quelle = "W:\Hörspiele Temp\PlayerKopieren\*" $Temp = "W:\Hörspiele Temp\MediaKopieren\" $Temp2 = "W:\Hörspiele Temp\MediaKopieren\*" $Media = "\\MEDIA\Multimedia\Audio\Hoerspiele\Sortieren\" $MovedFilesMedia = "C:\temp\Logs\MP3Player\MovedFilesMedia.txt" $MovedFilesMp3 = "C:\temp\Logs\MP3Player\MovedFilesMp3.txt" $ScriptErrorsMedia = "C:\temp\Logs\MP3Player\ScriptErrorsMedia.txt" $ScriptErrorsMp3 = "C:\temp\Logs\MP3Player\ScriptErrorsMp3.txt" ##################################################################################### # Setzt Laufwerksbuchstaben des USB MP3 Players und Pfad zu Hörspielen zusammen. # # Falls nicht vorhanden, Exit! # ##################################################################################### Try { $H320 = "$H320Test\Music\Hörspiele" gci $H320 -ErrorAction stop } catch {$time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler! Vermutlich MP3 Player nicht angeschlossen, daher Pfad falsch: "+$_.exception.message,$time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf MP3 Player zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { # Stern vom ende des Pfades entfernen wenn vorhanden If($Quelle.substring($Quelle.length -1 ,1) -eq '*'){ $nQuelle = $Quelle.remove($Quelle.length - 1) } Else { $nQuelle = $Quelle } # Ordnerstruktur und Dateien Kopieren Get-ChildItem $nQuelle -Recurse | ForEach-Object { # Ziel Pfad zusammen bauen; in dem der Textteil vom Quellpfad und Zielpfad ausgetauscht ist $nZiel = (Join-Path $H320 ($_.Fullname.replace($nQuelle,''))) If($_.PSIsContainer){ # Verzeichnisse bearbeiten (ordnerstruktur anlegen) # Neuen Pfad zusammenbauen und neues (Unter-)Verzeichnis im Ziel anlegen New-Item -Path $nZiel -ItemType directory -Force -ErrorAction Stop | Out-Null } # end IF Else { # Datei mit Progress kopieren Copy-FileProgress -Path $_.Fullname -Destination $nZiel -ErrorAction Stop # Logfile schreiben @($_.fullname, $_.Lastaccesstime) | Out-file -Append $MovedFilesMp3 } # end Else } # end ForEach cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" exit} ##################################################################################### # Versucht Hörspiele auf NAS zu kopieren. Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. Falls Vorgang scheitert, Exit! # ##################################################################################### try { Copy-Item -Path $Temp2 -Destination $Media -container -force -recurse -ErrorAction Stop Get-ChildItem -Recurse $temp2 | ForEach-Object { $FilePath2 = $_.fullname, $_.Lastaccesstime $filepath2 | Out-file -Append $MovedFilesMedia} remove-Item -Path $temp2 -recurse -ErrorAction Stop cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFertig.vbs" } catch { $time = get-date -format f Add-Content $ScriptErrorsMedia ("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\VerschiebeMediaFehler.vbs" }
Please click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!- Bearbeitet Peter Kriegel Mittwoch, 9. Januar 2013 08:14
- Als Antwort markiert Sönke T Donnerstag, 10. Januar 2013 08:18
-
Hallo,
zu 2. Funktioniert, habe zumindest das Prinzip verstanden. Das Script auch auf das kopieren von Verzeichnissen zu erweitern habe ich allerdings nicht hinbekommen.
Zu: „Es gibt in der PowerShell zwei verschiedene ForEach ! Da musst du aufpassen…“ Alleine hierfür hat sich der Thread gelohnt! Danke für den Hinweis!Zum Script:
- Verstehe ich das richtig: Die reine Funktion kann so wie sie ist, ohne Anpassungen für jedes weitere Script verwendet werden?! Die Funktion wird einfach über Copy-FileProgress aufgerufen?
- Das Script funktioniert zur Hälfte. Der Kopiervorgang mit Progressbar funktioniert nun ohne Probleme. (Zeitlich habe ich mal gemessen: 2 Min. 30 Sek. Mit Progressbar. Ohne Progressbar 45 Sek! Kopiert wurde 518 MB, wobei die Dateien 90% zwischen 5-8 MB und 10% 50-60 MB groß waren).
- Was nicht funktioniert: Nach dem kopieren und dem erfolgreichen Aufruf des VB Scripts werden eigentlich die soeben kopierten Dateien nach $Temp verschoben. (Vermutlich der Part, den du vorher fälschlicherweise mit „Remove“ eingebaut hast. Hier noch mal der Grundcode mit Kommentaren.
####################################################### # Versucht Hörspiele auf MP3 Player zu kopieren. # # Bei Erfolg werden die soeben kopierten Daten nach # # $Temo verschoben #Logfiles werden für erfolgreichen # # oder fehlerhaften Vorgang angelegt. # # Falls Vorgang scheitert, Exit! # ####################################################### try { Copy-Item -Path $Quelle -Destination $H320 -container -force -recurse -ErrorAction Stop # Funktioniert nun ohne Probleme! Get-ChildItem -Recurse $Quelle | ForEach-Object { $FilePath = $_.fullname, $_.Lastaccesstime $filepath | Out-file -Append $MovedFilesMp3} # Log für Kopie zum MP3 Player und das verschieben nach $Temp move-Item -Path $Quelle -Destination $Temp -ErrorAction Stop # Das verschieben nach $Temp wird in deinem Script überspungen cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fertig.vbs" # Aufruf eines Hinweisfensters, funktioniert } catch { $time = get-date -format f Add-Content $ScriptErrorsMp3("Fehler aufgetreten: "+$_.exception.message, $time) cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fehler.vbs" # Aufruf bei Fehler, funktioniert. exit}
Der weitere Part ab # Versucht Hörspiele auf NAS zu kopieren.... # sollte dann ja vermutlich wieder funktionieren. Hier werden die kopierten und nach $Temp verschobenen Daten zum Nas kopiert, falls online. (Nicht wundern, dass ich erst nach $Temp verschiebe und nicht direkt vom Quellverzeichnis nach dem kopieren zur Nas verschiebe. So behalte ich schnell den Überblick, was schon kopiert wurde und was verschoben wurde). -
>>> Das Script auch auf das kopieren von Verzeichnissen zu erweitern habe ich allerdings nicht hinbekommen.
Verzeichnisse mit Unterverzeichnissen (rekursiv) zu Kopieren geht natürlich am einfachsten so wie du es machst mit dem Stern Copy-Item Pfad\* .
Wenn du aber die Dateien einzeln als Progress sehen willst, dann ist das gar nicht so einfach.
Für diesen Zweck musst du dann meinen Code nehmen. In meinem Code kannst du dann Copy-FileProgress gegen Copy-Item austauschen.
1. Verstehe ich das richtig: …
JA!
2. …Zeitlich gemessen…
Schon die Verwendung von Get-ChildItem | Copy-Item ist langsamer als ein nacktes Copy-Item Pfad\*.
Jeder Pipeline schritt kostet wieder etwas Zeit….
Die ForEach Schleife ist schneller als das ForEach-Object Cmdlet.
Ich benutze absichtlich hier das ForEach Cmdlet da jede Datei einzeln in der Pipeline verarbeitet wird es wird k kein Array benötigt.
Die ForEach($File in $Files){ … } Schleife benötigt aber ein Array das alle $Files enthält.
Ein Array für eine ForEach Schleife kann bei sehr vielen Dateien sehr viel Speicher verbrauchen, das ist ungünstig.
Bei einer geringen Anzahl an Objekten (kleine Datenmenge) ist es egal wann man das Cmdlet und wann die Schleife nimmt.
Frag Einstein! Geschwindigkeit ist Relativ! (Fahrrad, Auto, Schall , Flugzeug, Rakete, Licht, Zeitumkehr) ;-))
3. Was nicht funktioniert:…
Wenn du das Verschieben der Dateien ohne Progress machen willst dann füge einfach deine Zeile wieder vor der Cscript.exe ein:
…
move-Item -Path $Quelle -Destination $Temp -ErrorAction Stop
cscript.exe "C:\Program Files\Scripte\Andere Scripte\MP3Player\KopierenH320Fertig.vbs"
…
Wenn du dort auch Progress sehen willst musst du Bescheid sagen ;-)
Dann ändere ich meinen CodePlease click “Mark as Answer” if my post answers your question and click “Vote As Helpful” if my Post helps you.
Bitte markiere hilfreiche Beiträge von mir als “Als Hilfreich bewerten” und Beiträge die deine Frage ganz oder teilweise beantwortet haben als “Als Antwort markieren”.
My PowerShell Blog http://www.admin-source.info
[string](0..21|%{[char][int]([int]("{0:d}" -f 0x28)+('755964655967-86965747271757624-8796158066061').substring(($_*2),2))})-replace' '
German ? Come to German PowerShell Forum!