main page >programming tips (VB5/6) >  Check if a file exists     diese Seite auf deutsch diese Seite auf deutsch
 
In this article we are looking for a function to check whether a specific file exists, without using additional toolboxes like the FSO. To achieve this, we just query the attributes of the file in question using GetAttr(); if the file does not exist (or if we try to access a drive which is not ready), an error occurs which will be trapped.
People often use If Dir$(Filename) <> "" Then ... for this, but it is not recommended since then Dir$ funktion is not reentrant, that is, a call within another Dir$ loop would terminate the outer loop.

Public Function FileExists(ByVal Filename As String) As Boolean
'check whether a file exists; 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
            

The VB function GetAttr() used in the code above returns an Integer type variable (16bit). Internally the API function GetFileAttributes() is called which returns a Long variable (32bit). VB then converts the Long to an Integer.
This usually works fine, but it fails a soon as we try to check a file that has the flag FILE_ATTRIBUTE_VIRTUAL (&h10000& = 65536) set; this for instance applies for files in Windows Vista that are located in certain "special folders". The type conversation performed by VB then fails with runtime error 6 (overflow) since the value &h10000& cannot be represented in a signed 16bit variable.
This error can be avoided by simply bypassing the VB encapsulation which is a little outdated nowadays; we just call GetFileAttributes() directly:

'Declarations
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
'check whether a file exists; version 2
Dim l As Long
l = GetFileAttributes(Filename)
  If l <> INVALID_FILE_ATTRIBUTES Then
    FileExists = ((l And vbDirectory) = 0)
  End If
End Function
            

However, there is still a minor issue left. With certain system files (pagefile.sys, hiberfil.sys ...), both version 1 and 2 of the function fail because the system denies the attempt to query the attributes of these files. On the other hand, if this happens that is enough information to determine the existence of the file: if an access violation occurs, then the file must exist (thanks to Donald Lessau for the hint, the idea to solve the issue came from Karl E. Peterson):

'Declarations
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
'check whether a file exists; 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
            
With this final version 3 we are now failure-proof in any situation.
main page >  programming tips (VB5/6) >  this page