Hauptseite >Tips zu VB5/6 >  Vorhandensein einer Datei prüfen     view this document in English view this document in English
 
Gesucht ist eine Funktion, die das Vorhandensein einer Datei prüft, ohne dass Hilfsmittel wie das FSO benötigt werden. Dazu fragen wir einfach mit GetAttr() die Attribute der Datei ab; falls die Datei nicht existiert oder auf ein nicht bereites Laufwerk zugegriffen wird, greift die Fehlerbehandlung.
Die häufig verwendete Methode If Dir$(Filename) <> "" Then ... ist nicht zu empfehlen, da die Dir$-Funktion nicht reentrant ist, d.h. der Aufruf innerhalb einer Dir$-Schleife würde diese äussere Schleife terminieren.

Public Function FileExists(ByVal Filename As String) As Boolean
'Test, ob eine Datei existiert; Version 1
Dim i As Integer
Err.Clear
On Error Resume Next
i = GetAttr(Filename)
  If Err.Number = 0 Then
    FileExists = ((i And vbDirectory) = 0)
  End If
On Error GoTo 0
End Function
            

Die im obigen Ansatz verwendete VB-Funktion GetAttr() liefert ein Ergebnis vom Typ Integer (16bit) zurück. Intern ruft sie die API-Funktion GetFileAttributes() auf, die einen Wert vom Typ Long (32 bit) liefert. VB wandelt diesen Wert dann in einen Integer um.
Dies geht so lange gut, bis man die Funktion auf eine Datei ansetzt, bei der das Flag FILE_ATTRIBUTE_VIRTUAL (&h10000& = 65536) gesetzt ist; dies trifft z.B. unter Windows Vista auf Dateien zu, die in diversen "Special Folders" liegen. Die von VB vorgenommene Typumwandlung führt dann zu Laufzeitfehler 6 (Überlauf), da der Wert &h10000& nicht mehr als 16bit-Integer darstellbar ist.
Abhilfe schafft man am besten dadurch, dass man die VB-eigene Kapselung, die heutigen Anforderungen nicht mehr gewachsen ist, ganz einfach umgeht:

'Deklarationen
Public Declare Function GetFileAttributes Lib "kernel32" _
  Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Public Const INVALID_FILE_ATTRIBUTES As Long = -1

'***

Public Function FileExists(ByVal Filename As String) As Boolean
'Test, ob eine Datei existiert; Version 2
Dim l As Long
l = GetFileAttributes(Filename)
  If l <> INVALID_FILE_ATTRIBUTES Then
    FileExists = ((l And vbDirectory) = 0)
  End If
End Function
            

Ein kleines Problem bleibt noch: Version 1 und 2 der Funktion scheitern bei speziellen Systemdateien (pagefile.sys, hiberfil.sys ...). Der Grund liegt darin, dass die Abfrage der Attribute dieser Dateien vom System verweigert wird. Man kann diesen Fehlschlag aber entsprechend auswerten: wenn eine Zugriffsverletzung auftritt, muss die Datei existieren (danke an Donald Lessau für den Hinweis, Lösungsvorschlag von Karl E. Peterson):

'Deklarationen
Public Declare Function GetFileAttributes Lib "kernel32" _
  Alias "GetFileAttributesA" (ByVal lpFileName As String) As Long
Public Const INVALID_FILE_ATTRIBUTES As Long = -1
Public Const ERROR_SHARING_VIOLATION As Long = 32&

'***

Public Function FileExists(ByVal Filename As String) As Boolean
'Test, ob eine Datei existiert; Version 3
Dim l As Long
l = GetFileAttributes(Filename)
  If l <> INVALID_FILE_ATTRIBUTES Then
    FileExists = ((l And vbDirectory) = 0)
  ElseIf Err.LastDllError = ERROR_SHARING_VIOLATION Then
    FileExists = True
  End If
End Function
            
Mit dieser Version 3 der Funktion sollten Sie nun für alle Eventualitäten gerüstet sein.
Hauptseite >  Tips zu VB5/6 >  diese Seite