0

Given the below console application, I have a problem understanding the .net Framework behavior.

I do have an absolute path to a folder (Windows), that I want to create. To avoid a PathTooLongException during Directory.CreateDirectory() I check for that in advance by doing a Path.GetFullPath() for the path. However, this is not working for a reason I don't understand.

My questions are:

  • Why is this happening?
  • How can I (really, as in reliably) check if the path is to long before creating the directory

Notes: - Simply catching the Exception during creation is not a solution for me, because the real world application does the PathTooLong check and the actual createion this on different places where a lot of other path related stuff is happening in between. So it would simply be to late to check that.

Edit: I checked that Path.GetFullPath() does not modify the path, but left that out in my example for brevity.

Here is my example code:

using System;
using System.IO;

namespace PathTooLongExperiments
{
    class Program
    {
        static void Main(string[] args)
        {
            string pathThatFailsCreate =     @"C:\Users\qs\1234567\vkT7eYDrFL0lZzEVBwx3O-8GE632bW64IvUiCqjOHv00661Kh,lVminnGrM4Y82EKD6\qozVNx8NoSDOhGoTV1f4syjtciBfv0fLCN7iSaRBuiHtIfgHNGJDbKQ28G4uqIumKa-\DtfhThPUI7J4hGxkPUem11PZBofq1uqn-7xw9YjBODLRouNCKo7T7-ODTc,Qjed01R0\8GfPtnmuUANti7sN55aq27cW";
            TryCreateFolder(pathThatFailsCreate);

            string pathThatWorks =     @"C:\Users\qs\1234567\vkT7eYDrFL0lZzEVBwx3O-8GE632bW64IvUiCqjOHv00661Kh,lVminnGrM4Y82EKD6\qozVNx8NoSDOhGoTV1f4syjtciBfv0fLCN7iSaRBuiHtIfgHNGJDbKQ28G4uqIumKa-\DtfhThPUI7J4hGxkPUem11PZBofq1uqn-7xw9YjBODLRouNCKo7T7-ODTc,Qjed01R0\8GfPtnmuUANti7sN55aq27c";
            TryCreateFolder(pathThatWorks);

            Console.WriteLine("Done. Press any key");
            Console.ReadKey();
        }

        private static void TryCreateFolder(string path)
        {
            Console.WriteLine($"Attempting to create folder for path:    {path}");
            string checkedPath;
            try
            {
                checkedPath = Path.GetFullPath(path);
            }
            catch (PathTooLongException)
            {
                Console.WriteLine("PathToLong check failed!");
                Console.WriteLine($"Path length: {path.Length}");
                Console.WriteLine($"Path: {path}");
                Console.ReadKey();
                return;
            }

            try
            {
                Directory.CreateDirectory(checkedPath);
            }
            catch (PathTooLongException)
            {
                // Why is this possible? We've checked for path too long by    Path.GetFullPath, didn't we?
                Console.WriteLine("Could not create directory because the path was to long");
            }
        }
    }
}
ChrisM
  • 1,148
  • 8
  • 22
  • 2
    Does `Path.GetFullPath` apply any modification to the returned path? Did you check if `checkedPath` and `path` match? – Nitram Aug 23 '16 at 10:56
  • Chicken-and-egg problem. GetFullPath() is not just a string manipulation method, it has to hit the disk to resolve short names, reparse points, relative paths and stuff I didn't think of. You'll inevitably fall over on the same problem. Plenty of libraries around that backport the native api path names to .NET so the limit is extended to 32766 characters. – Hans Passant Aug 23 '16 at 10:58
  • It does not, I checked that, but left it out in my example for clarity. I'll edit my post to clarify – ChrisM Aug 23 '16 at 11:14
  • Why would you expect that `Path.GetFullPath` would validate the path? The only thing it does is give you the full path to the directory - that doesn't make it shorter than the path limit for `CreateDirectory`. .NET 4.6.2 doesn't block long paths by default when normalizing, if you want to rely on that, you need to use an app.config setting (AppContextSwitchOverride). – Luaan Aug 23 '16 at 11:40
  • @Luaan Because it says so in the documentation: https://msdn.microsoft.com/library/system.io.path.getfullpath(v=vs.110).aspx#Anchor_1 – Nitram Aug 23 '16 at 11:42
  • 1
    @Nitram You have to read very carefully - "system-defined maximum length". That has nothing to do with the limits of `CreateDirectory`, which is just one function in Windows API. The path limit is actually ~32k characters nowadays, but `CreateDirectory` still supports a maximum of 248 regardless. – Luaan Aug 23 '16 at 11:48
  • @Luaan I think most windows API functions apply this limit by default. Not sure if you can work around that using the .NET api at all. That sort of makes it the system defined maximum. – Nitram Aug 23 '16 at 11:53
  • 1
    @Nitram Actually, most work with long paths just fine (though some require you to use a UNC path), just make sure to call the Unicode version (no breaking change, since that was NT code, not 95 code). Windows 10 and .NET 4.6.2 finally took the bold step to change the limit (to ~32k), probably after usage analysis showed that applications that don't support long paths are rare enough nowadays. Don't ask me why they didn't support `CreateDirectory` for so long when many other APIs already worked fine :) But given how strongly MS feels about compatibility, they likely had the data to back it up. – Luaan Aug 23 '16 at 12:29
  • Chris: Assuming that you are using .NET 4.6.2 or newer, have you tried simply prefixing the long path with "\\?\" ? Also, check the links in this answer (and the comments) as the linked blog posts show how to enable long paths in Win32 using **gpedit.exe** and showing that a .NET app might need a manifest file with a particular line in it: https://stackoverflow.com/a/41337687/577765 – Solomon Rutzky May 22 '18 at 15:30

0 Answers0