[RESOLVED] Handling file path-names longer than 260-VBForums
Results 1 to 5 of 5

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
    2,674

    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.

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

    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"

    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} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista 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
    2,674

    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

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

    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"

    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} {GDI+ Classes/Samples} {Unicode Open/Save Dialog} {Icon Organizer/Extractor}
    {VB and DPI Tutorial} {XP/Vista 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
    2,674

    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

Posting Permissions

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



Featured


Click Here to Expand Forum to Full Width

Survey posted by VBForums.