Laden...

Überwachen des Fortschritts von Robocopy - wie?

Erstellt von Rico913 vor 3 Jahren Letzter Beitrag vor 3 Jahren 2.670 Views
R
Rico913 Themenstarter:in
95 Beiträge seit 2020
vor 3 Jahren
Überwachen des Fortschritts von Robocopy - wie?

Hi,

ich möchte ein ProgressBar verwenden, um das Kopieren von Dateien darzustellen. Leider werden mir bei File.Copy die Rechte verweigert, aber RoboCopy funktioniert.

Nun möchte ich im ProgressBar den Status von Robocopy anzeigen. Mir fehlt dazu die Idee und das Wissen.

Ich dachte mir, wenn ich vielleicht die Byte-Menge im Quellverzeichnis auslese und permanent die ByteMenge im Zielverzeichnis auslese und prozentual im Progressbar anzeigen lasse.

Würde das überhaupt funktionieren und welche Anweisung bräuchte ich da?

  1. Auslesen Bytemenge Quelle
  2. permanentes Auslesen Bytemenge Ziel - wahrscheinlich über ne Schleife
  3. Übertrag auf Progressbar

Oder gibt es eine bessere Lösung?

Danke euch!!

T
2.219 Beiträge seit 2008
vor 3 Jahren

Musst du über den BinaryWriter lösen.
Robocopy und File Klasse sind hier der falsche Ansatz.

Du musst dann einmalig die Größe der Quelldatei ermitteln, kannst du z.B. über FileInfo
Dann musst du über den BinaryWriter die Datei kopieren.
Beim kopieren musst du einfach die Anzahl der Bytes intern summieren und nach jedem Schreibvorgang über ein eigenes Event dann die Rückmeldung zur aktuellen geschrieben Byte Menge machen.

Hier müsstest du also eine Klasse anlegen, die ein Event zum zurückmelden der geschrieben Bytes liefert.
Dazu kannst du dir ggf. sowas wie einen "FileWriter" anlegen, der dann eben die Datei von A nach B kopiert und über ein Event nach jedem Schreibvorgang die Menge der geschrieben Bytes liefert.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

16.806 Beiträge seit 2008
vor 3 Jahren

Ich sehe das nicht wie T-Virus; ich sehe den Ansatz als praktikabel an - wenn auch nicht als hübsch.
Würde auch lieber auf Robocopy setzen als was eigenes mit dem BinaryWriter zu basteln -> Robycopy ist bewährt.

Deine Idee ist theoretisch möglich; Du könntest aber in Fallen laufen:

  • Das ständige Auslesen der Bytemenge wird Deine Kopiergeschwindigkeit negativ beeinflussen
  • Meines Wissens hat Robocopy die Möglichkeit direkt Dateien mit der Zielgröße zu erstellen. Das heisst, dass sofort die Gesamtgröße der Datei auf dem Dateisystem existiert und dann nur noch die Bytes übertragen werden; sowas beschleunigt Kopiervorgänge größerer Dateien immens. Damit ist Deine Überwachung dahin.

Edit: Hast Du eigentlich vorher eine Minute gegoogelt? 😉
Ich finde sofort passende Treffer mit fertigen Lösungen.
Google-Suche nach robocopy progress bar

R
Rico913 Themenstarter:in
95 Beiträge seit 2020
vor 3 Jahren

Gegoogelt? Na klar, aber das ist doch alles für PowerShell oder kann man das übertragen?

16.806 Beiträge seit 2008
vor 3 Jahren

Hä? 🤔 Natürlich kannst Du das übertragen, warum sollte das nicht gehen?

Und im Falle von PowerShell sieht das so aus, dass PowerShell ja "nur eine Scriptsprache" ist und auch im .NET Context läuft.

Aber die Sprache spielt null eine Rolle. Kannst es auch in PHP oder JavaScript adaptieren.

3.825 Beiträge seit 2006
vor 3 Jahren

Es gibt eine gute Klasse für schnelles Kopieren :

QuickIO.NET - Performante Dateioperationen

Ich benutze die schon lange und geht auch async mit Progressbar.

Grüße Bernd

Workshop : Datenbanken mit ADO.NET
Xamarin Mobile App : Finderwille Einsatz App
Unternehmenssoftware : Quasar-3

T
2.219 Beiträge seit 2008
vor 3 Jahren

@Abt
Soweit ich dies verstehe, will der TE dies umbedingt in C# lösen und nur generell den Status vom Datei kopieren wie bei Robocopy nachbauen.
Deshalb auch mein Vorschlag es nicht über Robocopy oder File.Copy, was den Status auch nicht liefern kann, eben mit einer eigenen Klasse lösen.

Wenn es aber nur um die Stumpfe Anzeige des Robocopy Progress geht, kann man sich den Umweg mit einer eigenen Klasse sparen.
Hier kann man dann auch Robocopy über Process starten und dann die Ausgabe von Robocopy in der eigenen Anwendung anzeigen, wenn dies den der gewünschte Ansatz ist.
Dann muss man auch nichts über die Dateien oder die aktuellen Byte Mengen wissen.

Hier fehlen mir dann doch etwas mehr Details um zu erkennen was nun der sinnvollste Ansatz wäre.
Entsprechend würden ein paar mehr Details wahrscheinlich allen Helfern für einen besseren Ansatz helfen.

Nachtrag:
Antwort von Th69 dürfte die Lösung sein, wenn es um die Robocopy Anzeige geht.
Dann muss man nichts mit Process Wursten.

T-Virus

Developer, Developer, Developer, Developer....

99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.

R
Rico913 Themenstarter:in
95 Beiträge seit 2020
vor 3 Jahren

Hey,

danke für eure Antworten. Nach vielen Trial and Error Versuchen habe ich eine, für meine Zwecke ausreichende, Lösung gefunden:


private static int CountFiles(string path)
        {
                DirectoryInfo DiInfo = new DirectoryInfo(path);
                return DiInfo.GetFiles().Length;
        }
        
       

        public void Tim_ProgressBarTIFcopy_Tick(object sender, EventArgs e)
            {
            string Quelle = "\\\\sdrsmalabp03\\malab$\\07_Mitarbeiter\\Rico\\Test\\Test_Quelle";
            string Ziel = "\\\\sdrsmalabp03\\malab$\\07_Mitarbeiter\\Rico\\Test\\Test_Ziel";
            int DateiAnzahl_Ziel = 0;
            int DateiAnzahl_Quelle;
            DateiAnzahl_Quelle = CountFiles(Quelle);
            progressBar1.Maximum = DateiAnzahl_Quelle;
            
            if (DateiAnzahl_Ziel == DateiAnzahl_Quelle)
            {
                Tim_ProgressBarTIFcopy.Enabled = false;
                progressBar1.Value = 0;
            }
            else
            {
                DirectoryInfo DiInfo = new DirectoryInfo(Ziel);
                DateiAnzahl_Ziel += DiInfo.GetFiles().Length;
                //label5.Text = "Status: " + DateiAnzahl_Ziel.ToString();
                progressBar1.Increment(DateiAnzahl_Ziel);
            }
        }

Vielleicht nicht ganz sauber aber läuft. Ich habe nach einigen Fehlversuchen mit der Dateigröße - siehe Abt:

  • Meines Wissens hat Robocopy die Möglichkeit direkt Dateien mit der Zielgröße zu erstellen. Das heisst, dass sofort die Gesamtgröße der Datei auf dem Dateisystem existiert und dann nur noch die Bytes übertragen werden; sowas beschleunigt Kopiervorgänge größerer Dateien immens. Damit ist Deine Überwachung dahin.

mich auf die Dateianzahl konzentriert...

R
Rico913 Themenstarter:in
95 Beiträge seit 2020
vor 3 Jahren

Zu früh gefreut .... das gelbe vom Ei ist es dann doch nicht 😦
Bei einem anderen Test mit größeren und mehreren Dateien hat sich rausgestellt, dass es nicht die Wirklichkeit wiedergibt, sondern einfach nur stumpf den Balken durchzieht.
Ich habe progressBar1.increment in progressBar1.value geändert:


 progressBar1.Maximum = DateiAnzahl_Quelle;

            if (DateiAnzahl_Ziel == DateiAnzahl_Quelle)
            {
                Tim_ProgressBarTIFcopy.Enabled = false;
                progressBar1.Value = 0;
                CmdImgCopy.Text = "Bilder kopieren";
            }
            else
            {
                DirectoryInfo DiInfo = new DirectoryInfo(Ziel);
                DateiAnzahl_Ziel += DiInfo.GetFiles().Length;
                label5.Text = "Status: " + DateiAnzahl_Ziel.ToString();
                //progressBar1.Increment(DateiAnzahl_Ziel);
                progressBar1.Value = DateiAnzahl_Ziel;
                CmdImgCopy.Text = DateiAnzahl_Ziel.ToString() + "/" + DateiAnzahl_Quelle;
            }

Dennoch habe ich bei Tests herausgefunden, dass ich Probleme mit der DateiAnzahl_Ziel habe. Eigentlich soll er schauen, wieviel Dateien im Zielverzeichniss vorhanden sind und diesen Wert mit den Dateien im Quellverzeichnis vergleichen. Sind beide gleich stoppt der Timer und der ProgressBar ist auf 100%.
Wenn ich DiInfo.GetFiles().Length nicht aufsummiere, sondern nur "=" setze bleibt DateiAnzahl_Ziel auf "1" stehen. Ich versteh mein Fehler nicht - sicher ein Knick in der Logik.

1
124 Beiträge seit 2012
vor 3 Jahren
   
                DateiAnzahl_Ziel += DiInfo.GetFiles().Length;                 
  

Warum der Progressbalken zu schnell vollläuft liegt vermutlich an der oben genannten Zeile. Du Summierst bei jedem "Tick" die Dateien im Zielverzeichnis auf.

Besipiel:
Tick| Reale Dateien im Zielverzeichnis|Dateien in Zielverzeichnis nach deiner Berechnung
1|2|2
2|2|4 <-- obwohl keine Datei hinzugekommen ist, addierst du nochmal 2 hinzu.
3|3|7

Gruß Thomas

R
Rico913 Themenstarter:in
95 Beiträge seit 2020
vor 3 Jahren

Danke Thomas .... diesen Ansatz hatte ich auch schon verfolgt und deswegen die Aufsummierung durch "=" ersetzt. Dann müsste doch der reale Wert angezeigt werden, aber es wird nur "1" angezeigt.

Die Funktion, um die Anzahl zu bestimmen, habe ich einzeln getestet und ich bekomme den realen Wert angezeigt, bspw. 60.

16.806 Beiträge seit 2008
vor 3 Jahren

Nur als kleine Info: es ist eine Methode und keine Funktion.
Funktionen in OOP sind was anderes.

Du kannst selbst Deinen Code debuggen um zu sehen, wo welcher Wert auftaucht und mit dem Vergleichen, was Du denkst.
[Artikel] Debugger: Wie verwende ich den von Visual Studio?

Debuggen löst 99,999% der Logikfehler.

Du kannst ja das Verhalten 1:1 von PowerShell übernehmen. Da hast Du ja eine Blaupause.
Musst quasi nur abschreiben.