Datei-Suche mit API

Dateien mithilfe des Win32-API suchen

Man kann es sich fast denken – die Win32-API Funktion ist die umfangreichste Variante. Bevor überhaupt eine Routine erstellt werden kann, sind einige modulglobale Deklarationen notwendig. Darüber hinaus benötigen diese Funktion 2 bestimmte Strukturen und Konstanten. Der nachfolgende Teil ist modulglobal zu hinterlegen; d.h. außerhalb einer Routine im Kopfbereich eines Moduls:

Beispiel:

Option Explicit
 
Const MAX_PATH = 260
Const INVALID_HANDLE_VALUE = -1
 
Type FILETIME
     dwLowDateTime      As Long
     dwHighDateTime     As Long
End Type
 
Type WIN32_FIND_DATA
     dwFileAttributes   As Long
     ftCreationTime     As FILETIME
     ftLastAccessTime   As FILETIME
     ftLastWriteTime    As FILETIME
     nFileSizeHigh      As Long
     nFileSizeLow       As Long
     dwReserved0        As Long
     dwReserved1        As Long
     cFileName          As String * MAX_PATH
     cAlternate         As String * 14
End Type
 
Declare Function GetWindowsDirectory Lib "kernel32" Alias _
                "GetWindowsDirectoryA" _
                (ByVal lpBuffer As String, _
                 ByVal nSize As Long) As Long
 
Declare Function FindFirstFile Lib "kernel32" Alias _
                "FindFirstFileA" _
                (ByVal lpFileName As String, _
                 lpFindFileData As WIN32_FIND_DATA) As Long
 
Declare Function FindNextFile Lib "kernel32" Alias _
                "FindNextFileA" _
                (ByVal hFindFile As Long, _
                 lpFindFileData As WIN32_FIND_DATA) As Long
 
Declare Function FindClose Lib "kernel32" _
                (ByVal hFindFile As Long) As Long

Nach diesen Vorbereitungen sind wir in der Lage, die API-Lösung zu erstellen:

Beispiel:

' Die API-Variante
Sub API_GetIniFiles()
 
    Dim uWFD        As WIN32_FIND_DATA  'Strukturvariable für API-Suche
    Dim sBuffer     As String           'Hilfsvariable
    Dim sWinDir     As String           'Windows-Ordner
    Dim lCounter    As Long             'Zählervariable
    Dim lResult     As Long             'API-Rückgabewert
    Dim lFile       As Long             'Datei-Handle
    Dim asFiles()   As String           'Datenfeld für die Ergebnisdateien
 
   'Zunächst das Windows-Verzeichnis ermitteln
    sBuffer = Space(260)
    lResult = GetWindowsDirectory(sBuffer, Len(sBuffer))
    If lResult <> 0 Then
          sWinDir = Left$(sBuffer, lResult)
         'Falls nicht vorhanden, einen Backslash anfügen
          If Right$(sWinDir, 1) <> "\" Then sWinDir = sWinDir & "\"
    Else: Exit Sub
    End If
   'Erste Suche starten
    lFile = FindFirstFile(sWinDir & "*.ini", uWFD)
   'Wenn es ein gültiges Dateihandle gibt
    If lFile <> INVALID_HANDLE_VALUE Then
        lCounter = 0
        Do
           'Zählervariable für das Array vergrößern
            lCounter = lCounter + 1
           'Array um 1 Eintrag erweitern (Re-Dimensionieren)
            ReDim Preserve asFiles(lCounter)
           'In dem neuen Array-Eintrag den ersten Dateinamen speichern
            asFiles(lCounter - 1) = uWFD.cFileName
           'Feld in der Struktur initialisieren
            uWFD.cFileName = vbNullString
       'Solange weitersuchen, bis kein Treffer mehr vorliegt
        Loop While FindNextFile(lFile, uWFD)
       'Dateihandle explizit schließen!
        lFile = FindClose(lFile)
    End If
   'Ergebnistest - alle Array-Einträge im Direktfenster ausgeben
    For lCounter = LBound(asFiles) To UBound(asFiles)
        If Len(asFiles(lCounter)) > 0 Then
            Debug.Print "Eintrag"; lCounter; ": "; asFiles(lCounter)
        End If
    Next
 
End Sub

Mit dieser 3. Variante schließen wir die Dateisuche ab – welche Variante zu bevorzugen ist, ist letztendlich Geschmacksache. Je nach Art und Menge der zu suchenden Dateien gibt es durchaus zeitliche Unterschiede, wobei wohl die API-Variante die Schnellste (aber auch Aufwändigste) ist.