0

I am working on a Visual Basic project where we develop a Word tab. I have met with a problem that when the user use a word document whose path exceeds 255 characters, it gives the below error.

Unexpected error 9105 : String is longer than 255 characters.

I have searched in the web how the "255" created and found that

There is a limitation in Windows, maximum absolute file path length for a file / folder is MAX_PATH (which is defined as 260).

Also found that,

The full path of the Microsoft Office document includes the drive letter or server name, and all characters and folder names up to and including the name of the document. The entire path cannot be longer than 242 characters in Word, or 218 in Excel.

Also I found while doing testings for the issue, when the file path length is 254, then also we have the same error, and it is because of the invisible NUL terminator.

255 = 254 + 1 (NUL terminator)

Could anybody please explain me how this "255" created? What is the theory?

Thank you.

ApsSanj
  • 549
  • 7
  • 23
  • 2
    I'm voting to close this question as off-topic because this question is about a design decision made by Microsoft and does not appear to be related to development. – BryanH Aug 09 '18 at 20:29
  • Are you trying to solve a problem, or are you just asking out of curiosity? (Nothing wrong with being curious - but if you have a specific issue and can provide details you may get better responses) – StayOnTarget Aug 13 '18 at 10:58
  • @DaveInCaz I was solving a problem and I thought I need to have a proper understanding about the '255' number. I can explain '260' or '242' to user, but unable to explain 255. In this issue, I have instructed to just give a warning to user when they proceed with documents/images/videos/audios with high path length that exceeds 255, So using "GetLongPathNameA" (I had a situation that some long paths has been shortened by the system, but gives errors when proceed with our application, so extract the long path name in order to give the warning.) , I did my implementation. – ApsSanj Aug 14 '18 at 07:26

2 Answers2

3

I can't tell you precisely why the OS designers decided to confine the length to 260 characters, beyond that I'm sure that memory allocation considerations had something to do with it. But I can tell you a trick to shorten path names so that there are only eight characters per directory (otherwise known as 8.3 aliasing). That will allow path names that are 27 levels deep, which should solve most, if not all, of your problems.

If you have this path name:

C:\my long directory\my other long directory name\my long directory again\my long file.txt

the short version would be:

C:\MYLONG~1\MYOTHE~1\MYLONG~2\MYLONG~1.TXT

To get the short path name programmatically (borrowed from here):

Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal longPath As String, ByVal shortPath As String, ByVal shortBufferSize As Long) As Long

'The path you want to convert to its short representation path.
Dim longPathName As String

longPathName = "C:\my long directory\my other long directory name\my long directory again\my long file.txt"

'Get the size of the string to pass to the string buffer.
Dim longPathLength As Long

longPathLength = Len(longPathName)

'A string with a buffer to receive the short path from the api call…
Dim shortPathName As String

shortPathName = Space$(longPathLength)

'Will hold the return value of the api call which should be the length.
Dim returnValue As Long

'Now call the function to do the conversion…
returnValue = GetShortPathName(longPathName, shortPathName, longPathLength)

MsgBox(shortPathName)

You can use the short path name in any context that you would use the usual path name.

Since you're interested in the whys of things, Windows originally replaced MS-DOS, which allowed file names and/or directory names of up to eight characters only, with an optional three-character extension. Windows wanted to support longer file and path names without breaking compatibility with the DOS format, so they came up with this method of abbreviating long file names.

For more information, see Naming Files, Paths and Namespaces.

BobRodes
  • 5,990
  • 2
  • 24
  • 26
  • Even though this is not the answer for my question, this reply was really helpful. I had a situation that, some of my long file paths were automatically converted to 8.3 aliasing (short paths) and I was wondering how to identify those in my code, and referring your reply and other articles, I was able to get the long paths from the short paths. Thank you very much. – ApsSanj Aug 09 '18 at 11:18
  • 3
    @ApsSanj - You should be aware that it's possible for a system to have access to 8.3 names disabled. It's actually fairly common on servers. If you're writing for yourself, no problem. But if what you're writing may be distributed publicly, relying on 8.3 names could be a problem – Jim Mack Aug 09 '18 at 11:52
  • 2
    Preface the full path with ` \\?\ ` . This tells windows file functions YOU KNOW the paths is up to 32K (rather than the DOS\Windows standard of 260 bytes) and you allocated enough memory for it. This also works at the command prompt. Downside is that programs that follow windows' rules won't be able to access it, as they don't allocate enough memory to hold a string bigger than 260 bytes. The actual meaning of ` \\?\ ` is *turn off all windows filename check*. – CatCat Aug 09 '18 at 13:05
  • See http://stackoverflow.com/questions/41030190/command-to-run-a-bat-file/41049135#41049135 for the rules for a legal windows filename. – CatCat Aug 09 '18 at 13:12
  • @JimMack I forgot to bring that up!! Getting late I guess. Glad you caught it. – BobRodes Aug 10 '18 at 01:37
2

You can access very long pathnames using Unicode (the -W) functions. It's a bit more work but it's not all that difficult. Here's a Microsoft article on the topic. There are limitations (e.g. no relative paths) but overall it works well.

Also, MAX_PATH has been extended in the latest Win 10 update, but it requires a Group Policy edit to enable the new length.

Jim Mack
  • 1,070
  • 1
  • 7
  • 16