0

I am using the following code to check if a file exists:

If Len(Dir$(strFile)) > 0 Then

This worked fine until today.

In some cases I get the following error:

enter image description here

The error points to the line of code above.

I know the file doesn't exist, but I don't want this error to appear.

Hrqls
  • 2,944
  • 4
  • 34
  • 54

2 Answers2

4

I forgot to mention something: the filename is dynamic and depends on another process.

I just noticed that when the error occurs, the other process returns trash causing a long filename of about 2000 characters.

I never realized that there was a limit to the length of filenames.

I created a small project to test this and it turned out that the upper limit is 259 characters:

Option Explicit

Private Sub Command1_Click()
  Dim strFile As String
  Dim intLength As Integer
  strFile = App.Path & "\"
  intLength = 259 - Len(strFile)
  strFile = strFile & String(intLength, "a")
  If Len(Dir$(strFile)) = 0 Then
    MsgBox "file does not exist"
  End If
End Sub

Using a value of 259 works fine, but 260 gives the error.

Hrqls
  • 2,944
  • 4
  • 34
  • 54
  • 2
    +1 for answering own question and persistance. As for magic `260`, it is likely that `Dir$()` hits `MAX_PATH` limit: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx – Ilya Kurnosov May 07 '13 at 09:54
  • ah thanks! that's it indeed. would have been nice though if they would have provided another error than "file not found" :) – Hrqls May 07 '13 at 09:56
  • @Hrqls I suspect that the VB runtime simply copied 260 characters from the file string into a buffer of 260 characters (i.e. sized to MAX_PATH), thus implicitly truncating the file name to 259 chars (including null terminator). Not surprisingly, that file didn't exist. – Mark Bertenshaw May 07 '13 at 14:19
  • @MarkBertenshaw my line of code was there to check if the file exists. it works for shorter filenames for both existing and non existing files. so instead of just returning 0 it gave an error "file not found" while a "filename too long" would have been nicer :) – Hrqls May 08 '13 at 08:07
1

I use a function that calls into the Windows API to do this. This function handles spaces and long file names.

Add to the declarations section:

Private Declare Function CloseHandle Lib "Kernel32" (ByVal hObject As Long) As Long
Private Declare Function CreateFile Lib "Kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Any) As Long

Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Private Const OPEN_EXISTING = 3
Private Const FILE_SHARE_READ = &H1
Private Const GENERIC_READ = &H80000000
Private Const INVALID_HANDLE_VALUE = -1

The actual function

Function FileExists(ByVal fSpec As String) As Boolean
    Dim lngResult As Long
    Dim udtSA As SECURITY_ATTRIBUTES

    On Error GoTo errFileExists

    If Len(fSpec) > 0 Then
        udtSA.nLength = Len(udtSA)
        udtSA.bInheritHandle = 1&
        udtSA.lpSecurityDescriptor = 0&
        lngResult = CreateFile(fSpec, GENERIC_READ, FILE_SHARE_READ, udtSA, OPEN_EXISTING, 0&, 0&)
        If lngResult <> INVALID_HANDLE_VALUE Then
            Call CloseHandle(lngResult)
            FileExists = True
        Else
            Select Case Err.LastDllError  'some errors may indicate the file exists, but there was an error opening it
                Case Is = ERROR_SHARING_VIOLATION
                    FileExists = True

                Case Else
                    FileExists = False

            End Select
        End If
   End If

Exit Function

errFileExists:
    Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpFile, Err.HelpContext

End Function
jac
  • 9,666
  • 2
  • 34
  • 63