Rekursiv ab beliebigem Startpunkt alle Verzeichnisse durchlaufen - Performance optimieren

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Rekursiv ab beliebigem Startpunkt alle Verzeichnisse durchlaufen - Performance optimieren

    Hallo zusammen,

    ich bin neu hier und habe folgendes Problem:

    Ich habe ein Tool geschrieben, welches es ermöglicht, ab einem beliebigen Startpfad alle Unterordner zu durchlaufen, die darin enthaltenen Daten auszuwerten, eine Statistik dazu zu erstellen und hinterher, selektierte Dateien inklusive der Verzeichnisstruktur in einen beliebigen Zielpfad zu kopieren.

    Das funktioniert auch alles schon. Allerdings ist es bei Startpunkten mit extrem vielen Unterverzeichnissen und vielen Dateien wenig performant.

    Ich gehe davon aus, dass das zwei Ursachen hat - zum einen, die Rekursion beim Durchlaufen der Verzeichnisse, zum anderen die vielen Operationen mit long Datentypen, die für die statistische Auswertung der Daten notwendig sind.

    Gibt es eine Möglichkeit die Verzeichnisse ohne Rekursion zu durchlaufen, und habt ihr sonst Vorschläge zur Optimierung des Codes?

    Ich bin für jede Hilfe dankbar. Hier zunächst einmal der meines Erachtens nach "bremsende" Codeausschnitt:

    Quellcode

    1. ' Sub durchlaufe - Durchläuft die gesamte Struktur durch Rekursion
    2. Sub durchlaufe(path As String)
    3. On Error GoTo wartemarke
    4. ' Deklaration
    5. Dim name$, a%, i%
    6. ' Pfad anvisieren
    7. name = Dir(path, vbDirectory)
    8. ' a speichert die Ordnerstelle (Index), da Dir() nicht rekursiv speichert
    9. a = 0
    10. ' Hier passiert alles
    11. While name <> ""
    12. ' Wenn Ordner dann gehe rekursiv rein, sonst überprüfe Dateiendung
    13. If name <> "." And name <> ".." Then
    14. On Error Resume Next
    15. If (ordner(GetAttr(path & name))) Then
    16. On Error Resume Next
    17. durchlaufe(path & name & "\")
    18. On Error Resume Next
    19. name = Dir(path, vbDirectory)
    20. On Error Resume Next
    21. For i = 1 To a
    22. name = Dir()
    23. On Error Resume Next
    24. Next i
    25. Else
    26. ' Hier geschieht die Dateianalyse
    27. 'If Len(path & name) > 1 Then
    28. On Error Resume Next
    29. x = My.Computer.FileSystem.GetFileInfo(path & name).Length
    30. z = My.Computer.FileSystem.GetFileInfo(path & name).CreationTime
    31. y = dateiendung(name)
    32. alter = getalter(z)
    33. flag = False
    34. If alter = True Then
    35. alt = alt + x
    36. Else
    37. neu = neu + x
    38. End If
    39. If alter = True And y = "xlsm" Or y = "xlsx" Or y = "ppt" Or y = "pps" Or y = "ppsx" Or y = "pot" Or y = "pptx" Or y = "potx" Or y = "doc" Or y = "docx" Or y = "docm" Or y = "xls" Or y = "xlsx" Or y = "xlsm" Or y = "csv" Or y = "cal" Or y = "eml" Or y = "emm" Or y = "pdf" Or y = "txt" Or y = "vcf" Or y = "vcs" Then
    40. altoffice = altoffice + x
    41. flag = True
    42. ElseIf alter = False And y = "xlsm" Or y = "xlsx" Or y = "ppt" Or y = "pps" Or y = "ppsx" Or y = "pot" Or y = "pptx" Or y = "potx" Or y = "doc" Or y = "docx" Or y = "docm" Or y = "xls" Or y = "xlsx" Or y = "xlsm" Or y = "csv" Or y = "cal" Or y = "eml" Or y = "emm" Or y = "pdf" Or y = "txt" Or y = "vcf" Or y = "vcs" Then
    43. neuoffice = neuoffice + x
    44. flag = True
    45. End If
    46. If alter = True And y = "aac" Or y = "avi" Or y = "bmp" Or y = "emf" Or y = "gif" Or y = "ico" Or y = "jpeg" Or y = "jpg" Or y = "m4a" Or y = "mp3" Or y = "mp4" Or y = "png" Or y = "wav" Or y = "wma" Or y = "wmf" Or y = "wmv" Then
    47. altmultimedia = altmultimedia + x
    48. flag = True
    49. ElseIf alter = False And y = "aac" Or y = "avi" Or y = "bmp" Or y = "emf" Or y = "gif" Or y = "ico" Or y = "jpeg" Or y = "jpg" Or y = "m4a" Or y = "mp3" Or y = "mp4" Or y = "png" Or y = "wav" Or y = "wma" Or y = "wmf" Or y = "wmv" Then
    50. neumultimedia = neumultimedia + x
    51. flag = True
    52. End If
    53. If alter = True And y = "zip" Or y = "rar" Or y = "7z" Then
    54. altarchiv = altarchiv + x
    55. flag = True
    56. ElseIf alter = False And y = "zip" Or y = "rar" Or y = "7z" Then
    57. neuarchiv = neuarchiv + x
    58. flag = True
    59. End If
    60. If alter = True And flag = False Then
    61. altother = altother + x
    62. ElseIf alter = False And flag = False Then
    63. neuother = neuother + x
    64. End If
    65. zeile = zeile + 1
    66. End If
    67. End If
    68. If False Then
    69. wartemarke: zaehler = zaehler + 1
    70. End If
    71. 'End If
    72. a = a + 1
    73. ' Auf nächsten Ordner zugreifen
    74. name = Dir()
    75. On Error Resume Next
    76. End While
    77. End Sub
    78. Function ordner(i As Integer) As Boolean
    79. Dim a$
    80. a = ""
    81. While i <> 0
    82. If i Mod 2 = 1 Then
    83. a = "1" & a
    84. i = i - 1
    85. Else
    86. a = "0" & a
    87. End If
    88. i = i / 2
    89. End While
    90. If Len(a) < 5 Then
    91. ordner = False
    92. ElseIf "1" <> Mid(a, Len(a) - 4, 1) Then
    93. ordner = False
    94. Else
    95. ordner = True
    96. End If
    97. End Function
    Du nutzt also VB6 für dieses Programm? Wenn das wirklich so ist, würde ich mal schauen, um wie viel es in VB.NET schneller ist. Ich arbeite nebenbei an einem Dateisuchtool - das durchläuft mit C# ganze Laufwerke mit bis zu 1TB an Daten in ca. 30s. In VB.NET lässt sich die gleiche Performance erreichen.
    @nafets Jou.
    @MM215 Willkommen im Forum. :thumbup:
    In der Titelzeile steht VB6 und .NET 4.5.
    Das widerspricht sich.
    Dein Code sieht nach VB6 aus.
    Nimm bitte das .NET 4.5 oben wieder raus.
    und / oder
    Arbeite gleich mit .NET.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hallo,

    danke erstmal fürs Willkommen heißen.

    Also vielleicht kurz dazu:

    Ich habe vorher zwar schon einiges in verschiedenen Sprachen programmiert (C, Java, Cobol,...)

    Allerdings habe ich es bisher nie so zwingend nötig gehabt laufzeitkritisch zu programmieren...

    Ich habe mich dieses Mal für VB und Visual Studio 2015 entschieden, da es mir damit am einfachsten erscheint, eine saubere GUI zu "bauen".

    Mein Projekt im Visual Studio ist als Visual Basic .NET Framework 4.5.2 als Windows Forms Anwendung angelegt.

    Wenn ich eine Datenanalyse mit einem Startpfad starte, der nicht so "tiefe" Unterverzeichnisse enthält und ebenso nicht unzählige Dateien, dann funktioniert das auch alles schon ganz gut.

    Führe ich das Tool jedoch z.B. auf das gesamte C:\ Laufwerk aus, so dauert es vor allem wegen Ordnern wie C:\windows teilweise ca. eine Stunde. Ich gehe davon aus, dass das hauptsächlich an der Rekursion liegt, da die Aufrufe der extrem vielen Unterverzeichnisse wohl einfach zu viel sind.

    Wie ist das Durchlaufen mit C# denn aufgebaut, um solch eine Performance zu erzielen?

    Gibt es eine Möglichkeit die Rekursion in meinem Code Ausschnitt durch etwas einfacheres, schnelleres zu ersetzen?
    Erstmal hast du ein grundsätzliches Problem: Du nutzt fast nur Features, welche nur aus Kompatibilitätsgründen bzgl. VB6 vorhanden sind. Eigentlich solltest du für diesen Anwendungsbereich die Funktionen aus dem Namespace ​System.IO nutzen - speziell DirectoryInfo und FileInfo. Außerdem solltest du dein Programm in zwei Teile aufteilen: Die Auflistung der Ordner Dateien und Speicherung in einem Baum oder einer Liste & die Auswertung der Dateitypen.
    Was jedoch auch sehr wichtig ist, ist gute Fehlerbehandlung: ​On Error Resume Next - wie du es in deinem Code nutzt - ist nicht sauber. Eigentlich sollte man an allen Stellen wo Fehler auftreten können die erwarteten mit ​Try/Catch fangen und behandeln bzw. ignorieren.
    Ich kann mir auch vorstellen, dass die Auflistung bei Ordnern wie ​C:\Windows so lange dauert, weil ständig Exceptions autreten, da du keine ausreichenden Berechtigungen besitzt.

    Bei meinem Programm mache ich es grob folgendermaßen:
    1. Die rekursive Funktion kriegt einen Ordner (DirectoryInfo) übergeben
    2. Sie erstellt einen Enumerator auf die Dateien im Ordner,
    3. durchgeht den Enumerator Schritt für Schritt und fängt Exceptions bzgl. fehlenden Berechtigungen ab und
    4. fügt die gefundene Datei in die Liste hinzu
    5. Gleiches passiert nun für Ordner,
    6. jedoch wird bei jedem Ordner die Funktion nochmals auf den aktuellen Ordner aufgerufen, wodurch dieser rekursiv durchsucht wird.
    ​All diese Informationen packe ich in eine platzsparende Struktur, welche ungefähr so aussieht:

    VB.NET-Quellcode

    1. ​Public MustInherit Class MappedFileSystemObject
    2. Public Name As String
    3. Public Path As String
    4. End Class
    5. Public Class MappedFile
    6. Inherits MappedFileSystemObject
    7. Public Sub New(fileInfo As FileInfo)
    8. Me.Name = fileInfo.Name
    9. Me.Path = fileInfo.FullName
    10. End Sub
    11. End Class
    12. Public Class MappedFolder
    13. Inherits MappedFileSystemObject
    14. Public Sub New(name As String, path As String)
    15. Me.Name = name
    16. Me.Path = path
    17. Me.FileSystemObjects = New List(Of MappedFileSystemObject)()
    18. End Sub
    19. Public FileSystemObjects As List(Of MappedFileSystemObject)
    20. End Class

    Zuletzt verarbeite ich dann die Daten und speichere sie ab.

    Hoffentlich helfen dir die Ausführungen etwas bei deinem Projekt.

    Grüße
    Stefan :)

    MM215 schrieb:

    als Windows Forms Anwendung angelegt.
    Dann schmeiß allen VB6-Ranz raus.
    Mach zunächst ordentliche Einstellungen, bevor Du weitermachst.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich werfe dann mal Directory.GetFiles in die Runde.
    Da gibt's eine schöne Überladung, die sowohl ein SearchPattern als auch SearchOptions:=AllDirectories akzeptiert.
    Und schon sind 80% des ursprünglichen Code in einer einzelnen Zeile untergebracht.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Zunächst nochmals danke für die vielen, sehr guten Anmerkungen und Ideen. Das war schon sehr hilfreich.
    Ich habe aktuell zwei Varianten erstellt und würde gerne die Performance gegeneinander testen.

    Da das Programm im Anschluss an die Datenanalyse einen Kopiervorgang der selektierten Daten ausführen soll und dieser Kopiervorgang aufgrund hoher Datenmengen auch über Nacht möglich sein soll, ist es enorm wichtig das Exception Handling so aufzubauen, dass das Programm trotz auftretenden Exceptions nie eine Userinteraktion benötigt oder gar abbricht.

    Im folgenden Codebeispiel habe ich häufig eine "System.UnauthorizedAccessException".

    Meine Frage ist es nun, wie ich diese am besten behandle, um einen Abbruch zu verhindern und die Überprüfung der nächsten Datei / des nächsten Verzeichnisses einleite.

    Quellcode

    1. ​Sub Main()
    2. Dim di As DirectoryInfo = New DirectoryInfo(quelle)
    3. For Each fi In di.GetFiles("*", SearchOption.AllDirectories)
    4. x = fi.FullName.Length
    5. y = dateiendung(fi.Name)
    6. alter = getalter(fi.LastWriteTime)
    7. flag = False
    8. If alter = False Then
    9. neu = neu + x
    10. Else
    11. alt = alt + x
    12. End If
    13. If alter = True And y = "xlsm" Or y = "xlsx" Or y = "ppt" Or y = "pps" Or y = "ppsx" Or y = "pot" Or y = "pptx" Or y = "potx" Or y = "doc" Or y = "docx" Or y = "docm" Or y = "xls" Or y = "xlsx" Or y = "xlsm" Or y = "csv" Or y = "cal" Or y = "eml" Or y = "emm" Or y = "pdf" Or y = "txt" Or y = "vcf" Or y = "vcs" Then
    14. altoffice = altoffice + x
    15. flag = True
    16. ElseIf alter = False And y = "xlsm" Or y = "xlsx" Or y = "ppt" Or y = "pps" Or y = "ppsx" Or y = "pot" Or y = "pptx" Or y = "potx" Or y = "doc" Or y = "docx" Or y = "docm" Or y = "xls" Or y = "xlsx" Or y = "xlsm" Or y = "csv" Or y = "cal" Or y = "eml" Or y = "emm" Or y = "pdf" Or y = "txt" Or y = "vcf" Or y = "vcs" Then
    17. neuoffice = neuoffice + x
    18. flag = True
    19. End If
    20. If alter = True And y = "aac" Or y = "avi" Or y = "bmp" Or y = "emf" Or y = "gif" Or y = "ico" Or y = "jpeg" Or y = "jpg" Or y = "m4a" Or y = "mp3" Or y = "mp4" Or y = "png" Or y = "wav" Or y = "wma" Or y = "wmf" Or y = "wmv" Then
    21. altmultimedia = altmultimedia + x
    22. flag = True
    23. ElseIf alter = False And y = "aac" Or y = "avi" Or y = "bmp" Or y = "emf" Or y = "gif" Or y = "ico" Or y = "jpeg" Or y = "jpg" Or y = "m4a" Or y = "mp3" Or y = "mp4" Or y = "png" Or y = "wav" Or y = "wma" Or y = "wmf" Or y = "wmv" Then
    24. neumultimedia = neumultimedia + x
    25. flag = True
    26. End If
    27. If alter = True And y = "zip" Or y = "rar" Or y = "7z" Then
    28. altarchiv = altarchiv + x
    29. flag = True
    30. ElseIf alter = False And y = "zip" Or y = "rar" Or y = "7z" Then
    31. neuarchiv = neuarchiv + x
    32. flag = True
    33. End If
    34. If alter = True And flag = False Then
    35. altother = altother + x
    36. ElseIf alter = False And flag = False Then
    37. neuother = neuother + x
    38. End If
    39. Next
    40. End Sub


    Vielen Dank im Voraus.
    Dein Stil ist überaus grauenhaft, man könnte ihn auch "erschreckend furchtbar" nennen.
    Ehe du iwas anneres anfängst, mach erstmal wie Rod gesagt und verlinkt hat, die empfohlenen Einstellungen.
    Dann wird man sich mit Datentypen beschäftigen müssen - offenbar machst du zw. Integer und String überhaupt keinen Unterschied.
    Dann käme man zum Code-Design - deine Methode grabscht zig Variablen aus dem Nirvana ab, statt dass ihr nur genau die Parameter übergeben werden, die sie braucht.
    Dann noch einen vernünftigeren Umgang mit logischen Operatoren, und dann erst würde ich vorschlagen wendet man sich der UnAuthorisizedAccessException zu.
    uff

    MM215 schrieb:

    Ich habe vorher zwar schon einiges in verschiedenen Sprachen programmiert (C, Java, Cobol,...)
    Kann ich mir eigentlich nicht vorstellen, denn da solltest Du automatisch Option Strict On programmieren.
    Und x als Länge und y als Extension zu benennen - brrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Meine Güte...

    Das war doch einfach schnell runtergeschrieben, um die Funktion zu testen.

    Wenn ich das dann richtig umsetze, sieht das natürlich anders aus, aber für einen Entwurf ist das doch völlig Banane...

    Ich wollte da jetzt auch kein Feedback zu einem Entwurfsstil oder sonstiges, sondern hatte die konkrete Frage, wie man in einer for each Schleife sinnvoll Dateien bzw. Ornder überspringen kann, wenn keine Zugriffsrechte vorhanden sind.

    MM215 schrieb:

    Ich wollte da jetzt auch kein Feedback zu einem Entwurfsstil oder sonstiges, sondern hatte die konkrete Frage, wie man in einer for each Schleife sinnvoll Dateien bzw. Ornder überspringen kann, wenn keine Zugriffsrechte vorhanden sind.
    Kann man konkret schlecht beantworten, wenn kein (brauchbarer) Code vorliegt.

    Also Antwort generell: Dann musste in einem TryCatch die UnauthorisizedAccessException catchen und übergehen.

    Aber ist dir mit dieser Antwort geholfen?

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

    Snaptu schrieb:

    mal abgesehen davon gibt fi.Name() nicht nur die File-Extension zurück d.h. deine If-Abfrage funktioniert so garnicht.
    Nutze msdn.microsoft.com/en-us/libra…textension(v=vs.110).aspx
    Was steht eigentlich in getalter()?


    fi.Name() gibt natürlich nicht nur die File-Extension zurück. Daher dateiendung(fi.Name). Dort habe ich eine kleine function geschrieben, die mir dann die Extension von fi.Name zurückgibt.

    getalter ist eine function, die überprüft, wie lange es zurückliegt, dass die Datei das letzte mal geändert wurde und einen Boolean setzt, um zurückzugeben, ob die letzte Änderung länger als zwei Jahre zurückliegt oder nicht.
    für die Dateiendung brauchst du auch ne eigene Function? ;) naja wurscht aber willst du uns ernsthaft verklickern das du mit dem Gurken-Code da nur rumprobierst?
    Schreibst du dann das ganze nachher ein 2. mal neu oder wie? kauf ich dir ned ab. ein Konzept wies aussehen soll hättest dir auch auf nen Zettel schreiben können und dann abarbeiten.
    Wie wärs mit 1x schreiben dafür vernünftig? Alles was du brauchst steht in den Beiträgen hier im Thread. Ja und die Dateiendungen würd ich in ner Liste halten den so wie dus jetzt machst müsstest du bei ner Änderung in jeder
    Abfrage rumfummeln.

    EDIT: Sub Main () sieht nach ner Konsolenanwendung aus?
    Wer fragt, ist ein Narr für eine Minute. Wer nicht fragt, ist ein Narr sein Leben lang.

    ErfinderDesRades schrieb:

    MM215 schrieb:

    Ich wollte da jetzt auch kein Feedback zu einem Entwurfsstil oder sonstiges, sondern hatte die konkrete Frage, wie man in einer for each Schleife sinnvoll Dateien bzw. Ornder überspringen kann, wenn keine Zugriffsrechte vorhanden sind.
    Kann man konkret schlecht beantworten, wenn kein (brauchbarer) Code vorliegt.

    Also Antwort generell: Dann musste in einem TryCatch die UnauthorisizedAccessException catchen und übergehen.

    Aber ist dir mit dieser Antwort geholfen?




    Naja es geht um diese Schleife

    Quellcode

    1. ​For Each fi In di.GetFiles("*", SearchOption.AllDirectories)

    MM215 schrieb:

    Feedback zu einem Entwurfsstil oder sonstiges
    kriegst Du bei uns kostenlos mit. ;)
    Sieh Dir mal dies an:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.IO
    2. Public Class Form1
    3. Dim listOffice As List(Of String) = New List(Of String) From {"xlsm", "xlsx", "ppt", "pps", "ppsx", "pot", "pptx", "potx", "doc", "docx", "docm", "xls", "xlsx", "xlsm", "csv", "cal", "eml", "emm", "pdf", "txt", "vcf", "vcs"}
    4. Dim listmultimedia As List(Of String) = New List(Of String) From {"aac", "avi", "bmp", "emf", "gif", "ico", "jpeg", "jpg", "m4a", "mp3", "mp4", "png", "wav", "wma", "wmf", "wmv"}
    5. Dim listarchiv As List(Of String) = New List(Of String) From {"zip", "rar", "7z"}
    6. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    7. Dim quelle = "c:\Temp"
    8. Dim di As DirectoryInfo = New DirectoryInfo(quelle)
    9. Dim neu As Long = 0
    10. Dim alt As Long = 0
    11. Dim altoffice As Long = 0
    12. Dim neuoffice As Long = 0
    13. Dim altmultimedia As Long = 0
    14. Dim neumultimedia As Long = 0
    15. Dim altarchiv As Long = 0
    16. Dim neuarchiv As Long = 0
    17. Dim altother As Long = 0
    18. Dim neuother As Long = 0
    19. For Each fi In di.GetFiles("*", SearchOption.AllDirectories)
    20. Dim x = fi.FullName.Length
    21. 'y = dateiendung(fi.Name)
    22. Dim y = fi.Extension.ToLower.Substring(1)
    23. 'alter = getalter(fi.LastWriteTime)
    24. Dim alter = fi.LastWriteTime < New DateTime(2015, 3, 1)
    25. Dim flag = False
    26. If alter Then
    27. alt += x
    28. Else
    29. neu += x
    30. End If
    31. If listOffice.Contains(y) Then
    32. If alter Then
    33. altoffice += x
    34. Else
    35. neuoffice += x
    36. End If
    37. flag = True
    38. ElseIf listmultimedia.Contains(y) Then
    39. If alter Then
    40. altmultimedia += x
    41. Else
    42. neumultimedia += x
    43. End If
    44. flag = True
    45. ElseIf listarchiv.Contains(y) Then
    46. If alter Then
    47. altarchiv += x
    48. Else
    49. neuarchiv += x
    50. End If
    51. flag = True
    52. End If
    53. If Not flag Then
    54. If alter Then
    55. altother = altother + x
    56. Else
    57. neuother = neuother + x
    58. End If
    59. End If
    60. Next
    61. End Sub
    62. End Class
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Snaptu schrieb:

    für die Dateiendung brauchst du auch ne eigene Function? ;) naja wurscht aber willst du uns ernsthaft verklickern das du mit dem Gurken-Code da nur rumprobierst?
    Schreibst du dann das ganze nachher ein 2. mal neu oder wie? kauf ich dir ned ab. ein Konzept wies aussehen soll hättest dir auch auf nen Zettel schreiben können und dann abarbeiten.
    Wie wärs mit 1x schreiben dafür vernünftig? Alles was du brauchst steht in den Beiträgen hier im Thread. Ja und die Dateiendungen würd ich in ner Liste halten den so wie dus jetzt machst müsstest du bei ner Änderung in jeder
    Abfrage rumfummeln.

    EDIT: Sub Main () sieht nach ner Konsolenanwendung aus?




    Ich weiß immer noch nicht, wo das Problem ist. Ich hatte vorher eben noch nicht mit VB gearbeitet und auch nicht versucht Windows Verzeichnisstrukturen zu durchlaufen. Daher wollte ich einfach mal ein Verständnis dafür bekommen, wie dass so funktioniert und wie schnell das auf welche Art und Weise von statten geht. Das kann ich doch so alles viel besser ansehen und probieren, als auf Papier.

    Beim Probieren entsteht dann ja automatisch mein Konzept, weil ich dabei merke, was, wie gut funktioniert und mir entsprechend welche Vorteile/Möglichkeiten bringt.

    Und mit dem Wissen ist es dann für mich viel einfacher, dass sauber umzusetzen und JA ich schreibe dann den Code noch ein 2. mal von vorne unter Berücksichtigung aller gewonnenen Erkenntnisse während des Probierens.