Results 1 to 10 of 10

Thread: [RESOLVED] Handling file path-names longer than 260

  1. #1

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,937

    Resolved [RESOLVED] Handling file path-names longer than 260

    Ok, I'm attempting to develop wrappers for dealing with file specifications longer than 260 for real. I'm off to a slow (but good) start. But I've run into a problem. Here's what I've got for a BAS module:

    Code:
    
    Option Explicit
    '
    Private Const MAX_PATH_W    As Long = 32767&
    '
    Private Type SECURITY_ATTRIBUTES
        nLength As Long
        lpSecurityDescriptor As Long
        bInheritHandle As Long
    End Type
    '
    Private Declare Function GetLastError Lib "kernel32" () As Long
    Private Declare Function RemoveDirectoryW Lib "kernel32" (ByVal lpFileName As Long) As Long
    Private Declare Function CreateDirectoryW Lib "kernel32" (ByVal lpPathName As Long, lpSecurityAttributes As SECURITY_ATTRIBUTES) As Long
    Private Declare Function GetCurrentDirectoryW Lib "kernel32" (ByVal nBufferLength As Long, ByVal lpBuffer As Long) As Long
    Private Declare Function SetCurrentDirectoryW Lib "kernel32.dll" (ByVal lpPathName As Long) As Long
    '
    
    Public Function CurDirW() As String
        '
        ' CurDir replacement that deals with path > 260.
        ' Terminating slash is NOT placed on path (unless it's the root of a drive).
        '
        ' Limitations:  This version does NOT allow the specifying of a drive.
        '
        CurDirW = String$(MAX_PATH_W, 0&)
        CurDirW = Left$(CurDirW, GetCurrentDirectoryW(MAX_PATH_W, StrPtr(CurDirW)))
    End Function
    
    Public Sub ChDirW(ByVal sPath As String)
        '
        ' ChDir replacement that deals with path > 260.
        '
        ' Limitations:  This version does NOT allow relative path names.
        '
        ' Errors:   If all folders aren't found,  error 76.
        '           If some permission problem,   error 75.
        '
        Dim iRet As Long
        Dim iErr As Long
        '
        If Not AppendLongNamePrefix(sPath) Then Exit Sub
        AddSlash sPath ' Required for API call.
        iRet = SetCurrentDirectoryW(StrPtr(sPath))
        If iRet = 0 Then
            iErr = GetLastError
            Select Case iErr
            Case 2, 3               ' ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND.
                Err.Raise 76
            Case 5, 53              ' ERROR_ACCESS_DENIED, ERROR_BAD_NETPATH.
                Err.Raise 75
            Case Else
                Err.Raise 75
            End Select
        End If
    End Sub
    
    Public Sub MkDirW(ByVal sPath As String)
        '
        ' MkDir replacement that deals with path > 260.
        ' It only makes the last folder in the path.
        ' Terminating slash doesn't matter.
        '
        ' Limitations:  This version does NOT allow relative path names.
        '
        ' Errors:   If any/all other folders aren't found,  error 76.
        '           If folder (or filename) already exists, error 75.
        '           If some permission problem,             error 75.
        '
        Dim iRet As Long
        Dim iErr As Long
        Dim uSA As SECURITY_ATTRIBUTES
        '
        If Not AppendLongNamePrefix(sPath) Then Exit Sub
        AddSlash sPath ' Required for API call.
        uSA.nLength = LenB(uSA)
        iRet = CreateDirectoryW(StrPtr(sPath), uSA)
        If iRet = 0 Then
            iErr = GetLastError
            Select Case iErr
            Case 2, 3               ' ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND.
                Err.Raise 76
            Case 5, 53              ' ERROR_ACCESS_DENIED, ERROR_BAD_NETPATH.
                Err.Raise 75
            Case 183                ' ERROR_ALREADY_EXISTS.
                Err.Raise 75
            Case Else
                Err.Raise 75
            End Select
        End If
    End Sub
    
    Public Sub RmDirW(ByVal sPath As String)
        '
        ' RmDir replacement that deals with path > 260.
        ' It only removes the last folder in the path.
        ' Terminating slash doesn't matter.
        '
        ' Limitations:  This version does NOT allow relative path names.
        '
        ' Errors:   If any/all other folders aren't found,  error 76.
        '           If folder isn't empty,                  error 75.
        '           If some permission problem,             error 75.
        '
        Dim iRet As Long
        Dim iErr As Long
        '
        If Not AppendLongNamePrefix(sPath) Then Exit Sub
        AddSlash sPath ' Required for API call.
        iRet = RemoveDirectoryW(StrPtr(sPath))
        If iRet = 0 Then
            iErr = GetLastError
            Select Case iErr
            Case 0                  ' Not sure why, but this is what happens if files are in the folder.
                Err.Raise 75
            Case 2, 3               ' ERROR_FILE_NOT_FOUND, ERROR_PATH_NOT_FOUND.
                Err.Raise 76
            Case 5, 53              ' ERROR_ACCESS_DENIED, ERROR_BAD_NETPATH.
                Err.Raise 75
            Case Else
                Err.Raise 75
            End Select
        End If
    End Sub
    
    Public Function AddSlash(sFldr As String) As String
        ' Only adds it if not there.
        ' This can be used as EITHER a sub or function, as it modifies the input.
        If Right$(sFldr, 1) <> "\" Then sFldr = sFldr & "\"
        AddSlash = sFldr
    End Function
    
    Private Function AppendLongNamePrefix(ByRef sPath As String) As Boolean
        ' Returns true if successful.
        ' Error 75 is raised if failure.
        Select Case True
        Case Mid$(sPath, 2, 1) = ":"
            sPath = "\\?\" & sPath
        Case Left$(sPath, 2) = "\\"
            sPath = "\\?\UNC\" & Mid$(sPath, 3)
        Case Else
            Err.Raise 75
        End Select
        AppendLongNamePrefix = True
    End Function
    
    
    
    Now, everything works except for the ChDirW sub. It errors out when attempting to set a path that's longer than 260. The Microsoft documentation for SetCurrentDirectoryW says I should be good to go, but it doesn't work.

    Here's some test code to test it, if you like. As a caveat, be careful. I'm creating a folder too deep for Windows Explorer to delete. However, I've given you the code to both create it (button #1) and the code to delete it (button #3). Button #2 produces the error that I'm trying to figure out.

    To test, just throw above into a BAS module, create a form with three buttons, and throw the following into that form:

    Code:
    
    Option Explicit
    '
    Const iSubFolders = 29 ' 29 makes too long a path on C:, >260.
    '
    
    Private Sub Command1_Click()
        Dim sPath As String
        Dim i As Long
    
        sPath = "c:\"
        For i = 1 To iSubFolders
            sPath = sPath & "12345678\"
            MkDirW sPath
        Next i
    
    
        MsgBox "very long path created"
    End Sub
    
    Private Sub Command2_Click()
        Dim sPath As String
        Dim i As Long
    
    
        ' This attempts to change the path.
    
    
        sPath = "c:\"
        For i = 1 To iSubFolders
            sPath = sPath & "12345678\"
        Next i
    
        ChDirW sPath
    
        MsgBox "We've supposedly changed the current path to our long path.  Next, we'll show the current path."
        MsgBox CurDirW
    
    
        ChDirW "C:\" ' Put it back to c:\ so we don't get a sharing violation when we want to delete it.
    
    End Sub
    
    Private Sub Command3_Click()
        Dim sPath As String
        Dim i As Long
        Dim j As Long
    
    
        ' This deletes the long path.
    
        For j = iSubFolders To 1 Step -1
            sPath = "c:\"
            For i = 1 To j
                sPath = sPath & "12345678\"
            Next i
            RmDirW sPath
        Next j
    
        MsgBox "very long path deleted"
    End Sub
    
    I look forward to opinions on what I'm doing wrong.

    Regards,
    Elroy
    Last edited by Elroy; Mar 20th, 2017 at 02:39 PM.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  2. #2
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Handling file path-names longer than 260

    You may want to read the accepted answer at this site (read his last sentence)
    https://social.msdn.microsoft.com/Fo...elopmentissues

    Also, and just FYI. Starting with Win10, looks like you can get past the problem with a manifest. Mentioned about 2/3 way down the page
    https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx

    FYI: Your delete function failed for me. I just expanded about 5 levels deep and deleted the folder from that point, then deleted the root folder you created. No biggie.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  3. #3

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,937

    Re: Handling file path-names longer than 260

    Well then, okey dokey. In my primary project, I don't use ChDir or CurDir, but I thought they would be easy. I guess not. Well, I'm just going to delete those from my library.

    LaVolpe, thanks for the information.

    And yeah, I know that Win10 is attempting to solve many of these problems, but I'll be supporting Win7 for quite some time, and I do run into this problem, especially on server installations.

    Again, Thanks,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  4. #4
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: [RESOLVED] Handling file path-names longer than 260

    Well, a workaround could be to map a virtual drive to a long folder; may be worth looking into
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  5. #5

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,937

    Re: [RESOLVED] Handling file path-names longer than 260

    Nahhh, it's not worth the trouble to me. My first priority is to get my main application working with long file paths. Secondly, I'll try and reproduce all the VB6 file I/O with procedures to handle long file paths. I'm currently testing my Open...For Output procedures, and I use that quite often (as well as Input, Append, and Binary). I don't use Open...For Random.

    I'll report back when I get more up and running (and tested).

    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  6. #6
    Addicted Member
    Join Date
    Feb 2022
    Posts
    186

    Re: [RESOLVED] Handling file path-names longer than 260

    Quote Originally Posted by Elroy View Post
    ...I'll report back when I get more up and running (and tested).
    Elroy
    Elroy, this looked like a good project, any headway? Cheers

    I'm adding the reference LaVolpe mentioned because Microsoft has a habit of deleting pages:

    "Hello *Poor Groper

    This is a by-design behavior of the API.

    SetCurrentDirectory should only accept:
    1) input paths without a trailing '\' that have a maximum of (MAX_PATH - 2) non-NUL chars
    2) input paths with a trailing '\' that have a maximum of (MAX_PATH - 1) non-NUL chars

    \\?\ paths cannot exceed the above limitations. The 32,000 wide chars is not supported by SetCurrentDirectoryW for compatibility reasons.

    The doc of SetCurrrentDirectory does mention this:

    http://msdn.microsoft.com/en-us/libr...30(VS.85).aspx

    The string must not exceed MAX_PATH characters, including the terminating null character. The final character before the null character must be a backslash ('\'). If you do not specify the backslash, it will be added for you; therefore, specify MAX_PATH-2 characters for the path unless you include the trailing backslash, in which case, specify MAX_PATH-1 characters for the path."
    (*ad libitum taishan)
    Last edited by taishan; Aug 19th, 2023 at 09:02 PM.

  7. #7

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,937

    Re: [RESOLVED] Handling file path-names longer than 260

    Hi taishan,

    In my main application, in all cases, I do use UNC paths (with no drive mapping as mentioned above). And I do have installations where the 260 limit is a concern.

    To address this, I now use the GetShortPathNameW call before I attempt to open (or massage in any way) my files, and this completely solves the problem.

    We do have to be a bit careful with GetShortPathNameW, as the necessary DLL isn't installed by default on Windows Server OSs. However, it is installed on all Windows Desktop OSs (Windows 10, Windows 11, etc).

    This doesn't mean that your files can't be on a Windows server. It just means that your VB6 program that's calling GetShortPathNameW can't be executing on a Windows server (which would be rather rare).
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  8. #8
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Handling file path-names longer than 260

    GetShortPathNameW() is in Kernel32.dll as far as I can tell. Why would that be missing in Windows Server OSs?

  9. #9

    Thread Starter
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,937

    Re: [RESOLVED] Handling file path-names longer than 260

    Quote Originally Posted by dilettante View Post
    GetShortPathNameW() is in Kernel32.dll as far as I can tell. Why would that be missing in Windows Server OSs?
    Well, maybe it's not the API call that's missing, but the OS's setting to actually save the short path names. I don't remember all the details, but I just remember that, under certain circumstances, it wouldn't work.

    That actually brings up an interesting point. Maybe it is dependent on the file system, rather than the API call. In the settings where I've used it, I've never had it not work, but apparently there are cases where it doesn't. In those cases, I believe it just returns the long path name instead.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  10. #10
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: [RESOLVED] Handling file path-names longer than 260

    Yeah, it sounds like there are cases where there just isn't any "short name" to return depending on the filesystem or access protocol.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width