vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Brandneu! sevEingabe v2.0 - Das Eingabecontrol der Superlative!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   RSS-Feeds  | Newsletter  | Impressum  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2015
 
zurück
Rubrik: Dateisystem · Dateien - allgemein   |   VB-Versionen: VB2005, VB200808.12.08
Asynchrone FileScan API-Klasse

VB.NET Klasse zur Ermittlung aller Dateien eines Ordners/Unterordners, die mit einem bestimmten Such-Pattern übereinstimmen.

Autor:   Roland WutzkeBewertung:     [ Jetzt bewerten ]Views:  6.642 
www.vb-power.netSystem:  Win2k, WinXP, Vista, Win7, Win8 Beispielprojekt auf CD 

Summer-Special bei Tools & Components!
Gute Laune Sommer bei Tools & Components
Top Summer-Special - Sparen Sie teilweise über 100,- EUR
Alle sev-Entwicklerkomponenten und Komplettpakete jetzt bis zu 25% reduziert!
zum Beispiel:
  • Developer CD nur 455,- EUR statt 569,- EUR
  • sevDTA 2.0 nur 224,30 EUR statt 299,- EUR
  •  
  • vb@rchiv   Vol.6 nur 18,70 EUR statt 24,95 EUR
  • sevCoolbar 3.0 nur 58,70 EUR statt 69,- EUR
  • - Werbung -Und viele weitere Angebote           Aktionspreise nur für kurze Zeit gültig

    Die nachfolgende VB.NET Klasse ermittelt aufgrund des angegebenen SearchPattern alle Dateien eines Ordners und bei Bedarf auch deren Unterordner. Dabei wird eine gefundene Übereinstimmung (Treffer) über ein Event direkt an die aufrufende Form zurückgegeben. Die Klasse wird als Thread mit dem BackgroundWorker ausgeführt, so dass die Anwendung nicht einfriert. Der BackgroundWorker bietet weiterhin den Vorteil, dass wir uns nicht um threadübergreifende Zugriffe auf die GUI kümmern müssen - wir also nicht mit Invoke arbeiten müssen, so dass auch der weniger erfahrene VB-Programmierer problemlos mit der Klasse arbeiten kann.

    Durch die Verwendung der "FindFirstFile" und "FindNextFile" APIs erhalten wir den Vorteil, dass ein Treffer direkt zurückgegeben werden kann. Dies ist mit den DotNet Bordmitteln so nicht möglich, da uns System.IO.Directory.GetFiles erst ein String-Array zurückliefert, wenn die Suche abgeschlossen ist - was bei tiefen Verzeichnisbäumen schon mal ein bisschen dauern kann.

    Ein Treffer wird direkt über das Event ScannedFile zurückgegeben und kann in der GUI sofort verarbeitet werden.

    Nachfoldend die Klasse "FileScan":

    Imports System
    Imports System.IO
    Imports System.Runtime
    Imports System.Runtime.InteropServices
     
    ''' <summary>
    ''' Asynchrone FileScan API-Klasse
    ''' </summary>
    ''' <remarks>
    ''' Die Klasse ermittelt aufgrund des angegebenen SearchPattern alle Dateien
    ''' eines Folders und bei Bedarf auch deren Sub-Folder. Dabei wird eine
    ''' gefundene Übereinstimmung (Treffer) über ein Event direkt an die aufrufende
    ''' Form zurückgegeben. Die Klasse wird als Thread mit dem BackgroundWorker
    ''' ausgeführt, so dass die Anwendung nicht "einfriert".
    ''' 
    ''' http://www.vb-power.net
    ''' </remarks>
    Public Class FileScan
      Private WithEvents worker As New System.ComponentModel.BackgroundWorker
     
      Private m_StartFolder As String = String.Empty
      Private m_SearchPattern As String = "*.*"
      Private m_SearchOption As SearchOption = SearchOption.AllDirectories
      Private m_FileScanRunning As Boolean = False
     
      Public Event BeginScan(ByVal sender As Object, ByVal e As EventArgs)
      Public Event EndScan(ByVal sender As Object, ByVal e As EventArgs)
      Public Event ScannedFile(ByVal sender As Object, ByVal e As FileScanEventArgs)
      Public Event CurrentFolder(ByVal sender As Object, ByVal e As FileScanEventArgs)
    #Region "API Deklaration"
      Private Declare Auto Function FindFirstFile Lib "kernel32.dll" ( _
        ByVal lpFileName As String, _
        ByRef lpFindData As WIN32_FIND_DATA) As IntPtr
     
      Private Declare Auto Function FindNextFile Lib "kernel32.dll" ( _
        ByVal hFindFile As IntPtr, _
        ByRef lpFindData As WIN32_FIND_DATA) As IntPtr
     
      Private Declare Function FindClose Lib "kernel32.dll" ( _
        ByVal hFindFile As IntPtr) As Boolean
     
      <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
      Private Structure WIN32_FIND_DATA
        Public sfileAttributes As Int32
        Public creationTime_lowDateTime As Int32
        Public creationTime_highDateTime As Int32
        Public lastAccessTime_lowDateTime As Int32
        Public lastAccessTime_highDateTime As Int32
        Public lastWriteTime_lowDateTime As Int32
        Public lastWriteTime_highDateTime As Int32
        Public nFileSizeHigh As Int32
        Public nFileSizeLow As Int32
        Public dwReserved0 As Int32
        Public dwReserved1 As Int32
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=MAX_PATH)> _
        Public fileName As String
        <MarshalAs(UnmanagedType.ByValTStr, SizeConst:=14)> _
        Public alternateFileName As String
      End Structure
     
      Private Const MAX_PATH As Integer = 260
      Private Const INVALID_HANDLE_VALUE As Integer = -1
      Private Const FILE_ATTRIBUTE_DIRECTORY As Integer = &H10
    #End Region
    #Region "SearchParams"
      ''' <summary>
      ''' Interne Struktur zur Übergabe an den BGW
      ''' </summary>
      Private Structure SearchParams
        Dim StartFolder As String
        Dim SearchPattern As String
        Dim SearchOption As SearchOption
      End Structure
    #End Region
    #Region "FileScanEventArgs"
      ''' <summary>
      ''' Diese Event-Arg Klasse beinhaltet je ein Treffer und wird
      ''' mit den Events "ScannedFile" und "CurrentFolder" übergeben.
      ''' </summary>
      Public Class FileScanEventArgs
        Inherits EventArgs
     
        Public FileName As String = String.Empty
        Public FolderName As String = String.Empty
     
        Public Sub New(ByVal sFileName As String, ByVal sFolderName As String)
          Me.FileName = sFileName
          Me.FolderName = sFolderName
        End Sub
      End Class
    #End Region
    #Region "Properties"
      ''' <summary>
      ''' Gibt den Zustand des FileScans an
      ''' </summary>
      ''' <value>Boolean</value>
      ''' <returns>True, wenn der Scan läuft. Anderenfalls False.</returns>
      Public ReadOnly Property FileScanRunning() As Boolean
        Get
          Return m_FileScanRunning
        End Get
      End Property
      ''' <summary>
      ''' SearchPattern für den FileScan (Default: *.*)
      ''' </summary>
      ''' <value>Ein gültiger String mit dem Pattern</value>
      Public Property SearchPattern() As String
        Get
          Return m_SearchPattern
        End Get
        Set(ByVal value As String)
          If String.IsNullOrEmpty(value) Then
            Throw New Exception("SearchPattern darf nicht NULL sein")
          Else
            m_SearchPattern = value
          End If
        End Set
      End Property
      ''' <summary>
      ''' SearchOption für den FileScan (Default: AllDirectories)
      ''' </summary>
      Public Property SearchOption() As SearchOption
        Get
          Return m_SearchOption
        End Get
        Set(ByVal value As SearchOption)
          m_SearchOption = value
        End Set
      End Property
      ''' <summary>
      ''' Bestimmt den Start-Folder für den FileScan
      ''' </summary>
      ''' <value>Ein gültiger String mit dem StartFolder</value>
      ''' <remarks>UNC-Pfade sind zulässig</remarks>
      Public Property StartFolder() As String
        Get
          Return m_StartFolder
        End Get
        Set(ByVal value As String)
          If String.IsNullOrEmpty(value) Then
            Throw New Exception("StartFolder darf nicht NULL sein")
          Else
            m_StartFolder = value
            If Not m_StartFolder.EndsWith("\") Then
              m_StartFolder &= "\"
            End If
          End If
        End Set
      End Property
    #End Region
    #Region "Methoden"
     
      ''' <summary>
      ''' Startet den asynchronen Scan Vorgang
      ''' </summary>
      Public Sub StartScan()
        Dim p As New SearchParams
        p.StartFolder = m_StartFolder
        p.SearchPattern = m_SearchPattern
        p.SearchOption = m_SearchOption
     
        RaiseEvent BeginScan(Me, New EventArgs)
     
        Me.worker.WorkerReportsProgress = True
        Me.worker.WorkerSupportsCancellation = True
        Me.worker.RunWorkerAsync(p)
        m_FileScanRunning = True
      End Sub
      ''' <summary>
      ''' Beendet vorzeitig den Scan Vorgang
      ''' </summary>
      Public Sub CancelScan()
        If Me.worker.IsBusy Then
          Me.worker.CancelAsync()
        End If
      End Sub
      ''' <summary>
      ''' Interner BGW DoWork Event
      ''' </summary>
      Private Sub worker_DoWork(ByVal sender As Object, _
        ByVal e As System.ComponentModel.DoWorkEventArgs) _
        Handles worker.DoWork
     
        Dim p As SearchParams = DirectCast(e.Argument, SearchParams)
     
        Try
          Me.FindAllFiles(p.StartFolder, p.SearchPattern, p.SearchOption)
        Catch ex As Exception
          Throw New Exception(ex.Message)
        End Try
      End Sub
      ''' <summary>
      ''' Interner BGW ProgressChanged Event
      ''' </summary>
      Private Sub worker_ProgressChanged(ByVal sender As Object, _
        ByVal e As System.ComponentModel.ProgressChangedEventArgs) _
        Handles worker.ProgressChanged
     
        Select Case e.ProgressPercentage
          Case 0
            RaiseEvent ScannedFile(Me, New FileScanEventArgs( _
              e.UserState(0).ToString, e.UserState(1).ToString))
          Case 1
            RaiseEvent CurrentFolder(Me, New FileScanEventArgs( _
              e.UserState(0).ToString, e.UserState(1).ToString))
        End Select
      End Sub
      ''' <summary>
      ''' Interner BGW RunWorkerCompleted Event
      ''' </summary>
      Private Sub worker_RunWorkerCompleted(ByVal sender As Object, _
        ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
        Handles worker.RunWorkerCompleted
     
        m_FileScanRunning = False
        RaiseEvent EndScan(Me, New EventArgs)
      End Sub
      ''' <summary>
      ''' Interne API-FileFind Methode
      ''' </summary>
      Private Sub FindAllFiles(ByVal sStartFolder As String, _
        ByVal sSearchPattern As String, ByVal iSearchOption As SearchOption)
     
        Dim w32data As New WIN32_FIND_DATA
        Dim Handle As Integer = FindFirstFile(Path.Combine( _
          sStartFolder, "*.*"), w32data)
     
        If Handle <> INVALID_HANDLE_VALUE Then
          Do
            If Me.worker.CancellationPending Then
              FindClose(Handle)
              Return
            End If
     
            If (w32data.sfileAttributes And FILE_ATTRIBUTE_DIRECTORY) = _
              FILE_ATTRIBUTE_DIRECTORY AndAlso _
              iSearchOption = IO.SearchOption.AllDirectories Then
     
              If w32data.fileName <> "." And w32data.fileName <> ".." Then
                Me.worker.ReportProgress(1, New Object() {String.Empty, _
                  sStartFolder})
                FindAllFiles(Path.Combine(sStartFolder, w32data.fileName), _
                  sSearchPattern, iSearchOption)
              End If
            Else
              If w32data.fileName <> "." And w32data.fileName <> ".." Then
                If w32data.fileName Like sSearchPattern Then
                  Me.worker.ReportProgress(0, New Object() {Path.Combine( _
                    sStartFolder, w32data.fileName), sStartFolder})
                End If
              End If
            End If
          Loop Until FindNextFile(Handle, w32data) = False
     
          FindClose(Handle)
        End If
      End Sub
    #End Region
    End Class

    Anwendungsbeispiel:
    Platzieren Sie auf die Form ein ListBox-Control, ein Button mit der Beschriftung "Start" und ein Label-Control für die Ausgabe des aktuellen Ordners.

    Public Class Form1
      ' FileScan-Klasse mit Events
      Private WithEvents MyFileScan As New FileScan
     
      ' Anzahl Treffer
      Private FoundMatches As Integer
      ''' <summary>
      ''' Start/Stop des FileScans
      ''' </summary>
      Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Button1.Click
     
        Select Case MyFileScan.FileScanRunning
          Case False
            Try
              With MyFileScan
                ' Eigenschaften für den FileScan festlegen
                .StartFolder = "D:\"
                .SearchPattern = "*.txt"
                .SearchOption = IO.SearchOption.AllDirectories
     
                ' Scan starten
                .StartScan()
              End With
            Catch ex As Exception
              ' Fehler
              MsgBox("Fehler!" & vbCrLf & ex.Message, MsgBoxStyle.Exclamation)
            End Try
     
          Case True
            ' Filescan beenden
            MyFileScan.CancelScan()
        End Select
      End Sub
      ''' <summary>
      ''' Neuer Scan-Vorgang
      ''' </summary>
      Private Sub MyFileScan_BeginScan(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles MyFileScan.BeginScan
     
        FoundMatches = 0
        ListBox1.Items.Clear()
        Button1.Text = "Stop"
      End Sub
      ''' <summary>
      '''  Ausgabe des aktuellen Ordners
      ''' </summary>
      Private Sub MyFileScan_CurrentFolder(ByVal sender As Object, _
        ByVal e As FileScan.FileScanEventArgs) Handles MyFileScan.CurrentFolder
     
        Label1.Text = e.FolderName
      End Sub
      ''' <summary>
      '''  Scan-Vorgang beendet
      ''' </summary>
      Private Sub MyFileScan_EndScan(ByVal sender As Object, _
        ByVal e As System.EventArgs) Handles MyFileScan.EndScan
     
        Button1.Text = "Start"
        MsgBox("Anzahl gefundener Übereinstimmungen: " & FoundMatches, _
          MsgBoxStyle.Information)
      End Sub
      ''' <summary>
      ''' Ergebnis der Liste hinzufügen
      ''' </summary>
      Private Sub MyFileScan_ScannedFile(ByVal sender As Object, _
        ByVal e As FileScan.FileScanEventArgs) Handles MyFileScan.ScannedFile
     
        ListBox1.Items.Insert(0, e.FileName)
        FoundMatches += 1
      End Sub
    End Class

    Dieser Tipp wurde bereits 6.642 mal aufgerufen.

    Voriger Tipp   |   Zufälliger Tipp   |   Nächster Tipp

    Über diesen Tipp im Forum diskutieren
    Haben Sie Fragen oder Anregungen zu diesem Tipp, können Sie gerne mit anderen darüber in unserem Forum diskutieren.

    Neue Diskussion eröffnen

    nach obenzurück


    Anzeige

    Kauftipp Unser Dauerbrenner!Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv  Vol.6
    (einschl. Beispielprojekt!)

    Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv!
    - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten
    - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look
    Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m.
     
       

    Druckansicht Druckansicht Copyright ©2000-2015 vb@rchiv Dieter Otter
    Alle Rechte vorbehalten.

    Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

    Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel