0

For Each File In Folder.Files works fine as long as the lengths of the file names (incl. Path) are within the limit of Windows, which is 259 characters. But if a file name (incl. Path) is longer, then it doesn't work.

Here's an example:

ShortPath = "C:\TEST"
LongPath = "C:\TESTLONG"
Set FSO = CreateObject("Scripting.FileSystemObject")
Call FSO.CreateFolder(ShortPath)
Call FSO.CreateTextFile(ShortPath & "\" & String(240, "A"), True)
Call FSO.CreateTextFile(ShortPath & "\" & String(250, "B"), True)
Call FSO.MoveFolder(ShortPath, LongPath)
Set Folder = FSO.GetFolder(LongPath)

For Each File In Folder.Files
  Msgbox("File: " & File.Name & vbCrLf & "Length: " & Len(LongPath & "\" & File.Name))
Next

By renaming the folder "C:\TEST" to "C:\TESTLONG", the length of the file name "AAA..." (incl. path) is 252 (12+240) characters, which is still less than 260 characters. Therefore this file is listed.
But the length of the file name "BBB..." (incl. path) is now 262 (12+250) characters, which is more than 259 characters, which means that it's not listed.

Is there a way to identify file names (incl. path) that are too long?
Remark: I'd like to check the length of each file (incl. Path) in a directory and all its subdirectories.

user692942
  • 16,398
  • 7
  • 76
  • 175
Seeky
  • 78
  • 1
  • 9
  • Okay, but I'm not sure if it's really a problem of VBScript, because also with the Windows Explorer the file "BBB..." can't be opened after the directory has been renamed to "C:\TESTLONG\". – Seeky Jan 03 '21 at 04:26

1 Answers1

4

Approach 1: Use NT Object Path-style paths:

See Hans' answer in this QA: Access files with long paths (over 260)

Basically, change your paths to use \\?\ as a prefix:

Btw, I modified your code as follows:

  • Using Option Explicit
  • Removing the Call keyword from function invocation statements, note that parentheses must be omitted when not using Call.
  • Using camelCase for locals.
Option Explicit ' ALWAYS use Option Explicit!

Dim shortPath: shortPath = "\\?\C:\TEST"
Dim longPath : longPath  = "\\?\C:\TESTLONG"

Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateFolder shortPath

Dim streamA, streamB
Set streamA = fso.CreateTextFile( shortPath & "\" & String(240, "A"), True )
Set streamB = fso.CreateTextFile( shortPath & "\" & String(250, "B"), True )

fso.MoveFolder shortPath, longPath

Dim folder
Set folder = fso.GetFolder( longPath )

Dim file
For Each file In folder.Files
    Dim msg: msg = "File: " & file.Name & vbCrLf & "Length: " & Len(longPath & "\" & File.Name)
    Msgbox(msg)
Next

Approach 2:

  1. Set HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled to DWORD 1.

  2. Add or edit the Application Manifest for cscript.exe and wscript.exe to add these elements:

    <application xmlns="urn:schemas-microsoft-com:asm.v3">
        <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
            <ws2:longPathAware>true</ws2:longPathAware>
        </windowsSettings>
    </application>
    
Dai
  • 141,631
  • 28
  • 261
  • 374
  • Yes, the prefix ```\\?\``` solves the problem. Many thanks for your great help and all the additional information. – Seeky Jan 04 '21 at 18:02