Klasse zum rekursiven Kopieren von Verzeichnissen

    • VB.NET

    Es gibt 16 Antworten in diesem Thema. Der letzte Beitrag () ist von Nofear23m.

      Klasse zum rekursiven Kopieren von Verzeichnissen

      Moin,

      da ich gerade an einem Updater bin, benötigte ich eine Funktion zum rekursiven Kopieren von Dateien. Ich denke auch manch anderer wird sie gut gebrauchen können.
      Optional kann man zudem ein Modus angeben welche Dateien in das Zielverzeichnis kopiert werden sollen.

      OverwritesAll = Alle überschreiben
      OnlyNewFiles = Nur wenn die Datei am Zielort noch nicht existiert
      OverwriteNewDate = Nur wenn die Datei vom Quellort ein aktuelleres Datum hat als die Datei am Zielort

      Zudem verfügt sie über ein Event, welches ausgeführt wird, nachdem ein Verzeichnis erstell oder eine Datei kopiert wurde.
      Hierbei kann man direkt den aktuellen Status ausgeben lassen. Jedoch werden die Logs auch in eine Liste geschrieben und wird als Rückgabe der Funktion zurückgegeben.

      clsFilesystem.vb
      Spoiler anzeigen

      VB.NET-Quellcode

      1. Imports System.IO
      2. Public Class Filesystem
      3. Private Report As New List(Of CopyReport)
      4. Public Event Update(ByVal Report As CopyReport)
      5. Public Enum CopyMode
      6. OverwritesAll = 0
      7. OverwriteNewDate = 1
      8. OnlyNewFiles = 2
      9. End Enum
      10. Public Function CopyRecursive(ByVal SourcePath As String, ByVal DestinationPath As String) As List(Of CopyReport)
      11. Return CopyRecursiveMethode(SourcePath, DestinationPath, CopyMode.OverwritesAll)
      12. End Function
      13. Public Function CopyRecursive(ByVal SourcePath As String, ByVal DestinationPath As String, ByVal Mode As CopyMode) As List(Of CopyReport)
      14. Return CopyRecursiveMethode(SourcePath, DestinationPath, Mode)
      15. End Function
      16. Private Function CopyRecursiveMethode(ByVal SourcePath As String, ByVal DestinationPath As String, ByVal CopyMode As CopyMode) As List(Of CopyReport)
      17. Dim DirInfo As New DirectoryInfo(SourcePath)
      18. Dim Directories As List(Of DirectoryInfo) = DirInfo.GetDirectories.ToList
      19. Dim Files As List(Of FileInfo) = DirInfo.GetFiles.ToList
      20. For Each oDir As DirectoryInfo In Directories
      21. Dim NewDestinationPath As String = Path.Combine(DestinationPath, oDir.Name)
      22. Dim ReportClass As New CopyReport
      23. If Not Directory.Exists(NewDestinationPath) Then
      24. Directory.CreateDirectory(NewDestinationPath)
      25. ReportClass.Status = CopyReport.FileStatus.CreateDir
      26. ReportClass.Message = NewDestinationPath
      27. Report.Add(ReportClass)
      28. RaiseEvent Update(ReportClass)
      29. End If
      30. CopyRecursiveMethode(oDir.FullName, NewDestinationPath, CopyMode)
      31. Next
      32. For Each oFile As FileInfo In Files
      33. Dim ReportClass As New CopyReport
      34. Dim NewFilename As String = Path.Combine(DestinationPath, oFile.Name)
      35. Dim Overwrite As Boolean = False
      36. Dim CopyFile As Boolean = False
      37. Select Case CopyMode
      38. Case Filesystem.CopyMode.OverwritesAll
      39. Overwrite = True
      40. CopyFile = True
      41. ReportClass.Status = CopyReport.FileStatus.Copy
      42. Case Filesystem.CopyMode.OnlyNewFiles
      43. If Not File.Exists(NewFilename) Then
      44. CopyFile = True
      45. ReportClass.Status = CopyReport.FileStatus.Copy
      46. End If
      47. Case Filesystem.CopyMode.OverwriteNewDate
      48. If File.Exists(NewFilename) Then
      49. If FileDateTime(oFile.FullName) > FileDateTime(NewFilename) Then
      50. Overwrite = True
      51. CopyFile = True
      52. ReportClass.Status = CopyReport.FileStatus.Update
      53. End If
      54. Else
      55. Overwrite = True
      56. CopyFile = True
      57. ReportClass.Status = CopyReport.FileStatus.Copy
      58. End If
      59. End Select
      60. Try
      61. If CopyFile Then
      62. File.Copy(oFile.FullName, NewFilename, Overwrite)
      63. ReportClass.Message = NewFilename
      64. End If
      65. Catch ex As Exception
      66. ReportClass.Status = CopyReport.FileStatus.CopyError
      67. ReportClass.Message = ex.Message & "[" & NewFilename & "]"
      68. End Try
      69. If Not ReportClass.Message = "" Then
      70. Report.Add(ReportClass)
      71. RaiseEvent Update(ReportClass)
      72. End If
      73. Next
      74. Return Report
      75. End Function
      76. End Class
      77. Public Class CopyReport
      78. Public Enum FileStatus
      79. Copy = 0
      80. Update = 1
      81. CreateDir = 2
      82. CopyError = 3
      83. End Enum
      84. Public Status As FileStatus
      85. Public Message As String
      86. End Class


      Anwendungsbeispiel:
      Benötigt wird eine Windows Forms Anwendung, eine Textbox und ein Button.

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Class Form1
      2. Private WithEvents Filesystem As New Filesystem
      3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      4. Filesystem.CopyRecursive("C:\temp\vb.net\source", "C:\temp\vb.net\destination", FilesystemClass.Filesystem.CopyMode.OverwriteNewDate)
      5. End Sub
      6. Private Sub Filesystem_Update(ByVal Report As CopyReport) Handles Filesystem.Update
      7. Select Case Report.Status
      8. Case CopyReport.FileStatus.Copy
      9. TextBox1.Text &= "*Kopiere: "
      10. Case CopyReport.FileStatus.Update
      11. TextBox1.Text &= "*Update: "
      12. Case CopyReport.FileStatus.CreateDir
      13. TextBox1.Text &= "*Verzeichnis: "
      14. Case CopyReport.FileStatus.CopyError
      15. TextBox1.Text &= "**Fehler: "
      16. End Select
      17. TextBox1.Text &= Report.Message & vbNewLine
      18. End Sub
      19. End Class


      ohne Event

      Spoiler anzeigen

      VB.NET-Quellcode

      1. Public Class Form1
      2. Private WithEvents Filesystem As New Filesystem
      3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      4. Dim FileReport As New List(Of CopyReport)
      5. FileReport = Filesystem.CopyRecursive("C:\temp\vb.net\source", "C:\temp\vb.net\destination", FilesystemClass.Filesystem.CopyMode.OverwriteNewDate)
      6. For Each oFile As CopyReport In FileReport
      7. Select Case oFile.Status
      8. Case CopyReport.FileStatus.Copy
      9. TextBox1.Text &= "*Kopiere: "
      10. Case CopyReport.FileStatus.Update
      11. TextBox1.Text &= "*Update: "
      12. Case CopyReport.FileStatus.CreateDir
      13. TextBox1.Text &= "*Verzeichnis: "
      14. Case CopyReport.FileStatus.CopyError
      15. TextBox1.Text &= "**Fehler: "
      16. End Select
      17. TextBox1.Text &= oFile.Message & vbNewLine
      18. Next
      19. End Sub
      20. End Class

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Dodo“ ()

      Hallo Dodo,

      ich habe mir die Klasse angesehen, und ich finde sie Klasse.

      Leider blicke ich eins nicht.
      Gebe ich das Startverzeichnis an, kopiert er alles Recursive durch.
      Jedoch die Dateien die sich im angegebenen StartVerzeichnis befinden, die kopiert er nicht.
      Dort schreibt er in der TextBox
      Spoiler anzeigen
      **Fehler: Ein Teil des Pfades G:\PictureDrop\dotNetBase.Windows.Forms.dll konnte nicht gefunden werden.[G:\PictureDrop\dotNetBase.Windows.Forms.dll]
      **Fehler: Ein Teil des Pfades G:\PictureDrop\erfa09.png konnte nicht gefunden werden.[G:\PictureDrop\erfa09.png]
      **Fehler: Ein Teil des Pfades G:\PictureDrop\HttpPostRequestLib.dll konnte nicht gefunden werden.[G:\PictureDrop\HttpPostRequestLib.dll]
      **Fehler: Ein Teil des Pfades G:\PictureDrop\logo-takko.png konnte nicht gefunden werden.[G:\PictureDrop\logo-takko.png]
      **Fehler: Ein Teil des Pfades G:\PictureDrop\PictureDrop.exe konnte nicht gefunden werden.[G:\PictureDrop\PictureDrop.exe]
      **Fehler: Ein Teil des Pfades G:\PictureDrop\settings.xml konnte nicht gefunden werden.[G:\PictureDrop\settings.xml]
      **Fehler: Ein Teil des Pfades G:\PictureDrop\Thumbs.db konnte nicht gefunden werden.[G:\PictureDrop\Thumbs.db]
      **Fehler: Ein Teil des Pfades G:\PictureDrop\updateSystemDotNet.Controller.dll konnte nicht gefunden werden.[G:\PictureDrop\updateSystemDotNet.Controller.dll]


      Es ist dabei egal was ich vorher ausgewählt habe

      VB.NET-Quellcode

      1. Filesystem.CopyRecursive("C:\PictureDrop", "G:\PictureDrop", Filesystem.CopyMode.OverwritesAll)

      VB.NET-Quellcode

      1. Public Enum CopyMode
      2. OverwritesAll = 0
      3. OverwriteNewDate = 1
      4. OnlyNewFiles = 2
      5. End Enum


      Auch die Angaben des letzten \ bringt da nichts.

      Was mach ich falsch ?

      Danke

      Bernd

      Edit:
      ich weis das es eine Klasse für Verzeichnisse ist.
      Was mich aber wundert, wenn sie gleich zweimal hintereinander aufrufe, dann liest er ja die Files mit ein.
      Warum denn nicht beim ersten mal. Ich habe sie nun mehrfach durchgesehen, ich komme nicht drauf.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bernd“ ()

      Existiert beim ersten Mal das Verzeichnis PictureDrop schon? Evtl. ist dies der Fehler, ich prüfe ja mit FileExists, ob die Datei schon existiert, kann sein dass hierbei aucxh der Pfad geprüft wird und wenn dieser schon nicht existiert, dass es dann zu diesem Fehler kommt.

      Ggf. hilft es wenn man die Schleife mit den Dateien und den Verzeichnissen tauscht. Also das erst die Verzeichnie eingelesen und Rekursiv durchsucht und erst danach die Dateien kopiert werden. Bei den Verzeichnissen wird ja im Zielpfad dann das entsprechende Verzeichnis angelegt. War wohlmöglich ein Denkfehler von mir. Hab nur gerade keine Zeit das zu testen.

      Dodo schrieb:

      Existiert beim ersten Mal das Verzeichnis PictureDrop schon?

      Ich habe beides versucht. Zuerst ohne das das Verzeichnis Existiert. Dann habe ich es manuell angelegt.
      Beides mal macht er es nicht.
      Was mich nur wundert, lasse ich die Routine 2 mal hintereinander laufen, dann gehts.

      Ich schaue mir die Klasse nochmals in Ruhe an. Am Wochenende.
      Irgendwie muss die doch ans laufen kommen.

      Danke dir

      bernd
      Ich glaube es ist besser wenn erst die Schleife kommt wo durch die Verzeichnisse gegangen wird und danach die Schleife mit den Dateien. Normal habe ich eine rekursive Methode auch immer so gemacht, wieso hier nicht, ich weiß es nicht.
      Nun ich könnte hier einfach mal die Schleifen autauschen, nur weiß ich nicht ob das Problem dann wirklich behoben ist =)

      Ich änder es hier mal und du könntest es ja dann mal Testen und bescheid geben ob es funktioniert.

      Edit: so ist geändert.
      Hallo Dodo,

      so bin mal ein Stündchen früher aufgestanden um zu Testen.
      Jetzt geht leider nichts mehr. Ich habe beide Methoden mal ausprobiert.
      Es kommt nun nichts mehr an, weder Files noch Folder.

      Ich habe Lokale Verzeichnisse gewählt und als Ziel einen USB Stick. Auch anders herum.
      Verschiedene Verzeichnis Namen und auch Platten. Wobei das ja keinen Problem sein sollte.

      Ne sorry


      Bernd
      Guten Tag "DoDo",

      Ich benütze in meinem Projekt deine Klasse für das Kopieren. Seine Funktion ist es meine HD's zu Backupen, da kann es vorkommen das die Kopier. Dabei kann es vorkommen das die "Pfade" länger als 248 Zeichen sind. Dise werden bei deiner "Klasse" als fehler ausgegeben.

      Meine Frage:

      Ist es möglich, diese "Dateien" Trotzdem zu Kopieren?

      Fehler Meldung:

      XML-Quellcode

      1. Der angegebene Pfad und/oder Dateiname ist zu lang. Der vollständig qualifizierte Dateiname muss kürzer als 260 Zeichen und der Pfadname kürzer als 248 Zeichen sein.


      P.s. Bin bewundert von deiner "Klasse" die ist genial :)
      Natürlich, erstmal das Quellverzeichnis Rekusiv durchlaufen, alle Dateien mit Pfad in eine Liste speichern, damit die maximale Dateianzahl hast. Danach den Kopiervorgang starten, bei jeder Kopieroperation ein zähler hochzählen lassen und dann mittels 3-Satz aus bereits Kopierten Dateien und der maximal Dateianzahl den Prozentwert ermitteln und diesen dann einer Progressbar anzeigen lassen.
      Moin !

      auch wenn dieses Posting schon etwas angestaubt, so ist es doch genau das was ich suche.

      Meine Situation ist folgende:

      In einem Verzeichnis X:\VB_NET_2015\Rollout_Topobase gibt es ein Unterverzeichnis "x86" das samt seiner Subfolders und Dateien nach C:\Program Files\Autodesk\AutoCAD 2015\Map\bin kopiert werden soll.

      Mein Aufruf sieht nun wie folgt aus:

      VB.NET-Quellcode

      1. Dim FolderPathSubfolderSource As String = "X:\VB_NET_2015\Rollout_Topobase\x86"
      2. Dim FolderTarget As String = "C:\Program Files\Autodesk\AutoCAD 2015\Map\bin"
      3. Filesystem.CopyRecursive(FolderPathSubfolderSource, FolderTarget, Filesystem.CopyMode.OverwriteNewDate)


      Das Problem ist wohl aber das das Verzeichnis X86 nicht in das Zielverzeichnis kopiert wird.

      Ich kann aber als Basis nicht sagen, dass "X:\VB_NET_2015\Rollout_Topobase" als Basis angewandt werden kann, weil weitere Verzeichnisse auf dieser Ebene zu finden sind, die nicht übertragen werden sollen.

      Kann mir einer von Euch sagen, ob ich hier einen Gedankenfehler habe der kennt einen besseren Weg für das rekursive Kopieren? Wie gesagt, genau die Features der Überschreibung unter Beachtung der Zeitstempel sind genau passend für mich.

      Gruß Jan
      Hallo

      Ja und was spuckt dir die Klasse aus wenn du das Update-Event abonnierst??
      Da kannst du die Fehler ja auch mitloggen. Evtl. handelt es sich ganz simpel um Berechtigungs-Probleme.

      Grüße
      Sascha
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

      Moin!

      Berichtigung sollte es nicht sein.

      Wenn ich aber die Zeile

      VB.NET-Quellcode

      1. For Each oDir As DirectoryInfo In Directories


      debugge, dann wird bei

      VB.NET-Quellcode

      1. Dim FolderPathSubfolderSource As String = "X:\VB_NET_2015\Rollout_Topobase\x86"


      kein Subverzeichnis gelistet.

      Wird hingegen

      VB.NET-Quellcode

      1. Dim FolderPathSubfolderSource As String = "X:\VB_NET_2015\Rollout_Topobase"


      angewandt, dann werden 7 Verzeichnisse gelistet - also auch die anderen Verzeichnisse auf der Ebene".

      Scheint wohl ich das zu leisten was ich dachte also anpassen.

      vbarchiv.net/tipps/tipp_1597-o…rdner-kopieren-vbnet.html könnte es leisten.

      Gruß Jan
      @jan99
      BITTE implementiere das Event wie im Eingangspost ganz oben erklärt und logge anstatt in eine TextBox von mir aus mit Debug.WriteLine(Report.Message) aus.

      Ich verstehe das jetzt nicht ganz. Ich habe um die Loggs gebeten und es kommt nichts. DIESE Klasse schluckt leider Fehler komplett, weshalb du dir das so ausgeben lassen muss, oder man Debuggt richtig und setzt einen Haltepunkt.

      Also, bekommen wir nun die Infos welche die Klasse ausgibt?
      Ich habe ja selbst nur eine vermutung, möchte aber wissen ob diese korrekt ist um dir weiterhelfen zu können.

      Grüße
      Sascha
      If _work = worktype.hard Then Me.Drink(Coffee)
      Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

      ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##