Rekursives durchsuchen der Festplatte unter verwendung des Backgroundworkers

    • VB.NET

    Es gibt 7 Antworten in diesem Thema. Der letzte Beitrag () ist von ~blaze~.

      Rekursives durchsuchen der Festplatte unter verwendung des Backgroundworkers

      Hallo,

      hier ein Beispielcode unter verwendung des Backgroundworkers und den

      VB.NET-Quellcode

      1. FindFirstFile
      2. FindNextFile

      Apis.

      Dieses Beispiel soll zeigen, wie unter Verwendung des Backgroundworkers auf die Windows Form zugegriffen werden kann.
      Natürlich 'hängt' bei großen Mengen auch diese Windows Form !!!
      Was ein etwas anderes Vorgehen erfordern würde. :rolleyes:

      VB.NET-Quellcode

      1. Imports System
      2. Imports System.IO
      3. Imports System.Runtime
      4. Imports System.Runtime.InteropServices
      5. Imports System.ComponentModel
      6. Public Class Form1
      7. Private Declare Auto Function FindFirstFile Lib "kernel32.dll" (ByVal lpFileName As String, _
      8. ByRef lpFindData As WIN32_FIND_DATA) As IntPtr
      9. Private Declare Auto Function FindNextFile Lib "kernel32.dll" (ByVal hFindFile As IntPtr, _
      10. ByRef lpFindData As WIN32_FIND_DATA) As Boolean
      11. Private Declare Function FindClose Lib "kernel32.dll" (ByVal hFindFile As IntPtr) As Boolean
      12. <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
      13. Private Structure WIN32_FIND_DATA
      14. Public sfileAttributes As Int32
      15. Public creationTime_lowDateTime As Int32
      16. Public creationTime_highDateTime As Int32
      17. Public lastAccessTime_lowDateTime As Int32
      18. Public lastAccessTime_highDateTime As Int32
      19. Public lastWriteTime_lowDateTime As Int32
      20. Public lastWriteTime_highDateTime As Int32
      21. Public nFileSizeHigh As Int32
      22. Public nFileSizeLow As Int32
      23. Public dwReserved0 As Int32
      24. Public dwReserved1 As Int32
      25. <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> _
      26. Public fileName As String
      27. <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> _
      28. Public alternateFileName As String
      29. End Structure
      30. Private Const MAX_PATH As Integer = 260
      31. Private Const INVALID_HANDLE_VALUE As Integer = -1
      32. Private Const FILE_ATTRIBUTE_DIRECTORY As Integer = &H10
      33. Private WithEvents bgw As New BackgroundWorker
      34. #Region "Windows Forms Events"
      35. Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
      36. 'backgroundworker abbrechen, falls dieser noch beschäftigt ist
      37. If bgw.IsBusy = True Then
      38. bgw.CancelAsync()
      39. End If
      40. End Sub
      41. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      42. 'nötige backgroundworker einstellungen vornehmen
      43. bgw.WorkerReportsProgress = True
      44. bgw.WorkerSupportsCancellation = True
      45. End Sub
      46. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      47. 'hier ein array definieren, dass das startverzeichnis und das suchmuster enthält
      48. Dim arg() As String = {"c:\", "*.*"}
      49. bgw.RunWorkerAsync(arg)
      50. End Sub
      51. #End Region
      52. #Region "Backgroundworker"
      53. ''' <summary>Rekursives durchsuchen aller Ordner unterhalb des Startordners.</summary>
      54. ''' <param name="folder">Aktueller Ordner der durchsucht wird.</param>
      55. ''' <param name="pattern">Suchmuster z.b. *.*</param>
      56. ''' <remarks></remarks>
      57. Private Sub FindAllFiles(ByVal folder As String, ByVal pattern As String)
      58. Dim w32data As New WIN32_FIND_DATA
      59. Dim Handle As Integer = FindFirstFile(Path.Combine(folder, "*.*"), w32data)
      60. If Handle <> INVALID_HANDLE_VALUE Then
      61. Dim Search As Boolean = True
      62. Do
      63. 'Handelt es sich um ein Verzeichnis?
      64. If (w32data.sfileAttributes And FILE_ATTRIBUTE_DIRECTORY) = FILE_ATTRIBUTE_DIRECTORY Then
      65. 'Verzeichnisnamen ermitteln und für den späteren rekursiven Aufruf speichern
      66. If w32data.fileName <> "." And w32data.fileName <> ".." Then
      67. FindAllFiles(Path.Combine(folder, w32data.fileName), pattern)
      68. End If
      69. Else
      70. 'es ist eine datei
      71. If w32data.fileName Like pattern Then
      72. 'hier wurde eine datei als passend erkannt.
      73. 'aktionen wie z.b. kopieren usw. können hier angestossen werden
      74. 'soll auf die form zugegriffen werden, muss das im reportprogress event stattfinden
      75. bgw.ReportProgress(0, Path.Combine(folder, w32data.fileName))
      76. End If
      77. End If
      78. Loop Until FindNextFile(Handle, w32data) = False
      79. 'handle schliessen
      80. FindClose(Handle)
      81. End If
      82. End Sub
      83. Private Sub bgw_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork
      84. 'übergebene argumente zerpflücken und an bgw übergeben
      85. Dim arg() As String = e.Argument
      86. 'suche durch 1.aufruf der rekursiven funktion beginnen
      87. FindAllFiles(arg(0), arg(1))
      88. End Sub
      89. Private Sub bgw_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgw.ProgressChanged
      90. 'hier kann dann auf die windows-form zugegriffen werden
      91. Me.ListBox1.Items.Add(e.UserState)
      92. End Sub
      93. #End Region
      94. End Class

      Komentare erwünscht.

      Gruss

      mikeb69
      Hallo,

      ich hoffe es ist in Ordnung auf den Thread zu antworten,
      auch wenn er schon etwas älter ist.

      Mich würde aber interessieren wie man soetwas für mehr
      Dateien realisieren kann.

      Also ich möchte nur einen bzw mehrere bestimmte Dateitypen
      indexieren. Nur handelt es sich bei den zu indexierenden Dateien
      um 2000/~30000 (gesuchtes Dateiformat)/(alle Dateien in den Ordnern),
      und da dauert das gan schon ca eine Minute, in der das Programm
      als ausgelastet dargestellt wird.
      (Es wird aber während der indexierung (wahrscheinlich nicht so intelligent)
      noch verschiedene Aktionen mit dem File durchgeführt (DB abgleich, Bytereader))

      Mich würde interessieren wie man das effektiv für viele Dateien
      bzw für die komplette FEstplatte realisieren kann, und vor allem
      irgendwie einen Fortschritt darstellen kann.
      Das ändern eines Labels z.b. klappt irgendwie nicht.
      Wobei ich mir zu 99.99% sicher bin das es an mir liegt da ich recht neu
      in vb.net bin.
      Das ändern des Labels klappt erst nach dem vollständigen indexieren
      der Dateien.

      Hoffe es ist OK das ich hier gepostet habe, falls nicht kann man den Beitrag
      ja entfernen und ich mache einen neuen Thread im passenden Forum auf.

      Falls es keine "nicht zu aufwändige" Möglichkeit gibt das ganze für mehr
      Dateien auszulegen kann man mir vllt erklären wo/wie ich da jetzt das
      ändern eines Labels unterbringen kann, oder ob es irgendwie auch
      möglich ist, eine Art Fortschrittsbalken zu realisieren, ohne unnötig
      weitere Ressourcen zu verbrauchen.

      Danke.



      // Edit: Hat sich erledigt.
      Hab nun ein paar Sachen übernehmen können von denen ich angenommen
      hab das die unter VB nicht laufen würden, aber paar anpassungen und alles
      klappt wunderbar.
      Ist ja fast schon zu simpel, VB.Net :D

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

      Hinter der Funktion

      VB.NET-Quellcode

      1. My.Computer.FileSystem.GetFiles("Pfad", FileIO.SearchOption.SearchAllSubDirectories)

      steckt also so ein ähnlicher Code wie deiner?
      Gut zu wissen was hinter einer solchen Funktion steckt. :)

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

      Hi
      Das funktioniert so: Jedem Thread wird vom Betriebssystem aus eine bestimmte Zeit zum Arbeiten in der CPU gegeben. Anschließend werden alle Daten in den Registern usw. der CPU zwischengespeichert und das passiert dann auch für die anderen Threads. Wenn du jetzt einen BackgroundWorker erzeugst, arbeitet der wohl über einen neuen Thread, der ausgeführt wird. Der BackgroundWorker vereinfacht halt gewisse Vorgänge, die asynchron zu den anderen Threads des Programms ausgeführt werden sollen. Dies geschieht über Events. Events sind sozusagen Ansammlungen von Delegaten, die dann aufgerufen werden, wenn das Event ausgelöst wird. Der BackgroundWorker versteckt seinen Thread innerhalb der von ihm dargestellten Komponente und das Thread.Start() von dem Thread wird dann aufgerufen, wenn man ihm bescheid gibt, dass er zu arbeiten anfangen soll. In dieser Methode wird dann das Event ausgelöst.

      Gruß
      ~blaze~