.NET 4.6.2 and long paths on Windows 10


The Windows 10 Anniversary update is almost out the door. .NET 4.6.2 is in the update (as we’ve looked at in the past few posts). I’ve talked a bit about what we’ve done in 4.6.2 around paths, and how that is targeted at both allowing access to previously inaccessible paths and opens up the door for long paths when the OS has support. Well, as people have discovered, Windows 10 now has started to open up support. In this post I’ll talk about how to enable that support.

Enabling Win32 Long Path Support

Long paths aren’t enabled by default yet. You need to set a policy to enable the support. To do this you want to “Edit group policy” in the Start search bar or run “gpedit.msc” from the Run command (Windows-R).

In the Local Group Policy Editor navigate to “Local Computer Policy: Computer Configuration: Administrative Templates: All Settings“. In this location you can find “Enable Win32 long paths“.

Enabling Win32 long paths in the policy editor.

Enabling Win32 long paths in the policy editor.

After you’ve turned this on you can fire up a new instance of PowerShell and free yourself from the constraints of MAX_PATH! The key File and Directory Management APIs respect this and now allow you to skip the check for MAX_PATH without having to resort to using “\\?\” (look back to my earlier posts on path formats to understand how this works). This is also possible as PowerShell has opted into the new .NET path support (being that it is a .NET application).

If you look carefully at the description in the setting you’ll see “Enabling Win32 long paths will allow manifested win32 applications…“. That’s the second gate to getting support- your app must have a specific manifest setting. You can see what this is by opening C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe in Visual Studio or some other manifest viewer. Doing so you’ll see the following section in it’s manifest:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
  <windowsSettings>
    <longPathAware xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">true</longPathAware>
  </windowsSettings>
</application>

These two gates will get you the native (Win32) support for long paths. In a managed app you’ll also need the new behavior in .NET. The next section covers this.

Configuring a Simple Long Path .NET Console App

This example uses a new C# Console Application in Visual Studio 2015.

The first thing to do after creating a new console app is edit the App.Config file and add the following after the <startup> end tag:

<runtime>
  <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" />
</runtime>

If you have the 4.6.2 Targeting Pack installed (from the 4.6.2 Developer Pack) you can alternatively select 4.6.2 as your target framework in the project properties instead of using the app.config setting. The defaults for these two values are true if the target framework is 4.6.1 or earlier.

The second thing to do is add the Application Manifest File item to your project. After doing so add the windowsSettings block I shared above. In the default template there is already a commented-out section for windowsSettings, you can uncomment this and add this specific longPathAware setting.

Here is a sample block to add to your Main() method to test it out:

string reallyLongDirectory = @"C:\Test\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
reallyLongDirectory = reallyLongDirectory + @"\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
reallyLongDirectory = reallyLongDirectory + @"\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ\abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

Console.WriteLine($"Creating a directory that is {reallyLongDirectory.Length} characters long");
Directory.CreateDirectory(reallyLongDirectory);

You can open up PowerShell and go and look at the directory you created! Yayyyyyy!

This is the start of what has been a very long journey to remove MAX_PATH constraints. There is still much to do, but now the door is finally open. The rest can and will come- keep your feedback coming in to keep us on track!

The Windows support is documented on MSDN. APIs that aren’t listed may work- if the API took \\?\ in the past it will likely support the new behavior.

Note that in this initial release CMD doesn’t support long paths. The Shell doesn’t add support either, but previously had limited support utilizing 8.3 filename trickery. I’ll leave it to the Windows team for any further details.

Comments (34)

  1. T says:

    Looking forward to cmd.exe support for long paths

  2. Hi,

    I don’t really understand why this is not enabled by default in Windows 10 (1607), and also why this has to involve extra configuration set in the application (through the application manifest). Seems to be rather complicated to me.
    Is there any justified cost of enabling it without these extra steps (other than setting the .NET Framework to 4.6.2)?

    Thanks.

    1. JeremyKuhne says:

      Because other pieces were not ready (notably CMD) it was felt that off by default was best for the initial release.

      1. Richard Meadows says:

        What is not ready in cmd.exe? Prior to this, I have used cmd.exe as a work around for removing long paths in powershell scripts.

        1. JeremyKuhne says:

          Some limited things work in cmd- there are specific “hacks” to enable people to get out of scenarios like you describe. There are still a number of places where cmd uses fixed size buffers (mkdir for example).

  3. TK says:

    Will you reconsider on https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/2156195-fix-260-character-file-name-length-limitation?

    The year is 2016 and I just wasted hours today due to a TFS2015 build server that fails in the last “drop” step with “Exception Message: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters. (type PathTooLongException)” in Microsoft.TeamFoundation.Build.Workflow.Activities.WindowsDropProvider.

    An error like this is what I call “classic Microsoft quality”. I appreciate that you are finally doing something about it, but when will it really be solved/solvable?

    It would be great to be able to use just the .NET platform without the Windows legacy, so please keep improving .NET Core. Meanwhile, you have users suffering and getting increasingly annoyed by your decade old bugs.

    1. JeremyKuhne says:

      This is part of fixing that issue. This and the Windows side were key pieces to unblock the rest of the work. Some things can be solved immediately (i.e. PowerShell scripts, opting in custom tools via the config, etc). Because this initial support already solves some problems and allows easier development for the rest of the toolchain pieces we didn’t hold back on other things being finished (CMD for example). Your voices matter in this so please keep the feedback coming and point out your particular fail points (as you have).

      Fyi, .NET Core 1.0 works on any version of the OS with long paths without you needing to do anything. The work here originated in .NET Core- we’re primarily focusing there and pulling back improvements to 4.x where we can (such as this one).

      Incidentally, that issue was reopened as https://visualstudio.uservoice.com/forums/121579-visual-studio-2015/suggestions/4954037-fix-260-character-file-name-length-limitation. 🙂

  4. Cyber Sinh says:

    Hi, Good news.
    But not all IO .NET API seem to be compatible. If Directory.CreateDirectory() works as expected, File.Move() crashes again with a PathTooLongException… How can we know what .NET API are “long path aware” and what are not?
    Thanks.

    1. JeremyKuhne says:

      Can you give me an repro? It should work. Make sure you don’t have any segments over 255 characters- that is a limitation that is part of the NTFS specification (no file system on any platform supports more than that for file/directory names). There should be no APIs that choke on long paths when configured correctly (assuming the OS is enabled)- there are some that don’t work with \\?\ outside of mscorlib, but that is the only known limitation.

      1. Cyber Sinh says:

        Hi,
        Yes, you’re right. I had one segment that exceed 255 caracters in the path.

      2. Cyber Sinh says:

        The PathTooLongException message is confusing when you enable long path support : “The fully qualified file name must be less than 260…” which is not true. Do you plan to adapt the message depending on the context?
        Thanks.

        1. JeremyKuhne says:

          Yeah, the exception message isn’t accurate. I’ll look into updating it- hopefully to match what we have in CoreFx.

      3. skSdnW says:

        The policy description is a bit confusing because I don’t know what it means by node. The segment limit comes from the FS and has never been 260. IIRC the segment limit is surfaced as a DWORD to/from Win32 but unless ReFS changed it we are still stuck at 255. My second guess for what it means by node would be something related to reparse points and the object manager but I don’t see how the kernel32 layer where the MAX_PATH limit ends would care about them in this context. Can you explain what they mean by node here?

        1. JeremyKuhne says:

          I hadn’t noticed that, thanks. I have no idea on what they were trying to say by per node. I assume it was a mistake. I’ll let them know.

          You are correct that segment limits are part of file system specifications and have nothing to do with MAX_PATH. There are no file systems in common usage on any OS (Windows, Mac, Unix, etc.) that allow more than 255 for segments. There are a few that allow less (optical media notably). I’m unaware of any limitations where you can’t use the full segment length outside of a wacky max path limitation of 248 in CreateDirectory() that is also removed with the support enabled.

  5. Eugene says:

    I couldn’t create long path directory from your example. Windows 10 Home Build 1607, VS 15 Preview 3.
    The error says “System.IO.DirectoryNotFoundException: Could not find a part of the path”.

    1. JeremyKuhne says:

      You’ll need to give me a concrete example of the path you’re trying to create. It is possible you’re trying to create a path that is getting some part of itself normalized away.

      1. JohnyL says:

        The code was taken right from your example by copy/paste.

        1. JeremyKuhne says:

          I can’t reproduce your error. Validate that you have a correct app.config and app.manifest and that the manifest is inside your .exe (open it in VS to see it) and that you don’t have a standalone .manifest in your output directory that has different settings than the embedded one. Check that the path that you copied didn’t end up with spaces in it. Also, of course, make sure the policy is set and that you’ve restarted VS.

          Other than that you could be colliding with existing paths. Try your own long path(s).

          1. JohnyL says:

            It works! Thanks a lot! 🙂

        2. JohnyL says:

          Home Edition doesn’t have Group Policy Editor. Is there some other way to the the same?

          1. JeremyKuhne says:

            You can set the registry key directly. It’s “\Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\” with the “LongPathsEnabled” DWORD value set to 1.

  6. Marco Adriani says:

    Great news!
    The behavior of applications not supporting long paths will remain the same with files and folders created by applications that support them?

    1. JeremyKuhne says:

      They will be no different than they used to be when encountering paths that are longer than MAX_PATH. You could always create long paths on Windows if you used the extended device syntax (\\?\), and some frameworks and tools already create files this way. Win32 APIs take a buffer size- you won’t get a path back that is bigger than you specify. In the case of .NET apps they will still throw at MAX_PATH by default.

  7. vp says:

    var longpath = @”c:\temp\”+$”{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}{Guid.NewGuid()}”;

    Directory.CreateDirectory(longpath );

    still see this
    Unhandled Exception: System.IO.PathTooLongException: The specified path, file name, or both are too long. The fully qualified file name must be less than 260 characters, and the directory name must be less than 248 characters.
    at System.IO.LongPathHelper.Normalize(String path, UInt32 maxPathLength, Boolean checkInvalidCharacters, Boolean expandShortPaths)

    1. JeremyKuhne says:

      You can’t have segments over 255 characters. See my reply to skSdnW for more details.

  8. Do you have any news about support of long paths in Windows Server 2016? The TechPreview5 hasn’t got the option “enable win32 long paths” and Explorer is not able to manage path longer than 260 characters.

    1. JeremyKuhne says:

      Sorry, I don’t have any info on Server status. Explorer doesn’t handle long paths yet (modulo an existing partial support if it can create a <260 char 8.3 version of the path).

  9. I’ve tested c# code with Win 10 (1607) and works fine. My console app was able to write long paths adding the AppContextSwitchOverrides under . But it was not required to add a manifest. Why? Perhaps I haven’t completely understood you post. Manifest and app.config are two different options for managing long paths or need to be both used on the same app?

    1. JeremyKuhne says:

      It should require the manifest as well, I’ll look to see if I get the same behavior. Basically Windows has two gates, the registry (which you can set via the policy), and each app’s manifest. A normal (e.g. not “\\?\”) long path will fail in Win32 if those aren’t both set. It is possible that there is a bug in the logic, but the documentation requires the manifest setting.

      The app.config thing is specifically for .NET. It is technically a breaking change so if you want the behavior without targeting 4.6.2 you need to explicitly opt in via the app.config. (Or potentially opt out if you are targeting 4.6.2).

      1. Any news about this? Reading your response to MuiBienCarlota, it seems that a manifest file is not required and a modified app.config is enough to turn on the new behavior (on a system with 4.6.2 installed).

  10. I’ve run c# code similar to yours on a “regular” hard-disk and it worked fine. But it failed on a harddisk encrypted with BitLocker. Is it the expected behavior?

    1. JeremyKuhne says:

      I’m not aware of BitLocker specific issues, I’ll give it a try. I’ll let the Windows folks know.

  11. MuiBienCarlota says:

    I’ve Apps targeting .Net 4.6 and I would like to stay with it.
    Is there a way to benefit of long file name support when my Apps runs under .Net 4.6.2 on a properly configured Windows 10 1607 system?

    1. JeremyKuhne says:

      Use the AppContext switches in your .config file as described. That will turn on the behavior if 4.6.2 is installed and your app targets < 4.6.2.

Skip to main content