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: 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 11.900 mal aufgerufen.
Anzeige
![]() ![]() ![]() (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. |
sevISDN 1.0 ![]() Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats ![]() Dieter Otter PopUp-Menü wird nicht angezeigt :-( In diesem Tipp verraten wir Ihnen, wie Sie Probleme mit PopUp-Menüs umgehen können, wenn diese unter bestimmten Umständen einfach nicht angezeigt werden. sevZIP40 Pro DLL ![]() Zippen und Unzippen wie die Profis! Mit nur wenigen Zeilen Code statten Sie Ihre Anwendungen ab sofort mit schnellen Zip- und Unzip-Funktionen aus. Hierbei lassen sich entweder einzelnen Dateien oder auch gesamte Ordner zippen bzw. entpacken. |
||||||||||||||||
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. |