Condividi tramite


.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".

[caption id="attachment_525" align="alignnone" width="754"]Enabling Win32 long paths in the policy editor. Enabling Win32 long paths in the policy editor.[/caption]

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="https://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

  • Anonymous
    August 02, 2016
    Looking forward to cmd.exe support for long paths
  • Anonymous
    August 03, 2016
    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.
    • Anonymous
      August 03, 2016
      Because other pieces were not ready (notably CMD) it was felt that off by default was best for the initial release.
      • Anonymous
        August 24, 2016
        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.
        • Anonymous
          August 26, 2016
          The comment has been removed
    • Anonymous
      January 01, 2017
      Applications need to opt-in via a manifest, because only the application knows, whether it can support file names longer than MAX_PATH characters. PowerShell does, and contains the appropriate manifest.That means, that the group policy cannot be enabled by default, because there's the possibility of breaking PowerShell scripts, that were written against the documented contract, at a time when the MAX_PATH limit was still there.Yes, compatibility is complicated.
  • Anonymous
    August 03, 2016
    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.
    • Anonymous
      August 03, 2016
      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. :)
  • Anonymous
    August 05, 2016
    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.
    • Anonymous
      August 05, 2016
      The comment has been removed
      • Anonymous
        August 05, 2016
        Hi,Yes, you're right. I had one segment that exceed 255 caracters in the path.
      • Anonymous
        August 05, 2016
        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.
        • Anonymous
          August 06, 2016
          Yeah, the exception message isn't accurate. I'll look into updating it- hopefully to match what we have in CoreFx.
      • Anonymous
        August 10, 2016
        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?
        • Anonymous
          August 11, 2016
          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.
  • Anonymous
    August 06, 2016
    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".
    • Anonymous
      August 06, 2016
      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.
      • Anonymous
        August 06, 2016
        The code was taken right from your example by copy/paste.
        • Anonymous
          August 07, 2016
          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).
          • Anonymous
            August 08, 2016
            It works! Thanks a lot! :)
        • Anonymous
          August 07, 2016
          Home Edition doesn't have Group Policy Editor. Is there some other way to the the same?
          • Anonymous
            August 08, 2016
            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.
    • Anonymous
      November 10, 2017
      That's because you didn't enable the long path setting in gpedit.msc
  • Anonymous
    August 09, 2016
    Great news!The behavior of applications not supporting long paths will remain the same with files and folders created by applications that support them?
    • Anonymous
      August 09, 2016
      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.
  • Anonymous
    August 12, 2016
    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 thisUnhandled 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)
    • Anonymous
      August 15, 2016
      You can't have segments over 255 characters. See my reply to skSdnW for more details.
  • Anonymous
    August 22, 2016
    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.
    • Anonymous
      August 26, 2016
      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).
  • Anonymous
    August 22, 2016
    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?
    • Anonymous
      August 26, 2016
      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).
      • Anonymous
        September 06, 2016
        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).
  • Anonymous
    August 22, 2016
    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?
    • Anonymous
      August 26, 2016
      I'm not aware of BitLocker specific issues, I'll give it a try. I'll let the Windows folks know.
  • Anonymous
    August 24, 2016
    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?
    • Anonymous
      August 26, 2016
      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.
      • Anonymous
        September 21, 2016
        Can you get away with not updating windows, only installing .net 4.6.2, but still target and earlier version? Or does this require the latest version of windows 10 and .net 4.6.2 together?
        • Anonymous
          May 30, 2017
          You can use \?\ with any version of the OS if you have 4.6.2 or higher. Not using \?\ is a new OS feature. .NET Core supports downlevel without \?\ by taking care of \?\ for you.
  • Anonymous
    September 06, 2016
    After installing the .NET Framework 4.6.2 Developer Pack and setting the Enable Win32 long paths, I still cannot create a project in Visual Studio with a long path.Did I miss something or does Visual Studio 2015 need to be updated?Thank you,Karl
    • Anonymous
      May 30, 2017
      Visual Studio needs updated to support long paths. I know they're looking at getting it working, just not sure when it will get done. OS progress will be driving it I suspect.
  • Anonymous
    December 07, 2016
    Thanks! This helped a lot.
  • Anonymous
    March 22, 2017
    I'm able to get this to work on my local machine that runs windows 7 (seems to be no need for 10...) and I have created and moved file with very long paths and long file names.However it does not seem to work creating a file with a long path on a network share using the syntax \?\UNC\ .It seems that the max_path limitation is still valid for the network share. Do you know what needs to be in place for this to work on the network share? Does the policy have to be set on the machine that is serving the share or does the server has to be a current version? I querid the win32 api function GetVolumeInformation(...) to get information about that network but that only returns information about how long the path fragments (single dirs and files) may be (255 chars) and not about the maximum total path length of files / directories on the share.
    • Anonymous
      May 30, 2017
      \?\ has been around forever- you don't require any sort of setup to use it outside of .NET not supporting it until my changes. Try doing things from the command prompt with \?\ to see what limitations you have or don't have. I'm able to using both \?\UNC\ and \Server\Share with long paths on Creators Update from CMD when I've enabled on both ends.
  • Anonymous
    April 22, 2017
    I have some questions:* Will this feature (not having to use "\?" for long paths in my code) work with all Oses supporting .NET 4.6.2, or just Windows 10?* After Windows 10's Creators update, I can no longer use this code without it throwing an ArgumentException (It worked on 4.6.2 before the Creators update): DirectoryInfo directoryInfo = new DirectoryInfo(@"\?" + "someLongPathHere");Is that a bug?
    • Anonymous
      May 30, 2017
      There was a bug in Anniversary Update (RS1) that long paths would work without the manifest. That was fixed in Creators Update (RS2)- you need the manifest entry.
      • Anonymous
        December 14, 2017
        I have written a web application that needs to use long paths. With the Anniversary update, the web application worked fine, probably because of the bug that made it so an app.manifest was not required. However, when we updated to the Creators update (RS2), this application started throwing max path exceptions (assuming because the app.manifest bug had been fixed and now an app.manifest is required). From my research, it is not possible to simply add an app.manifest or throw the windows setting into the web.config since there seems to be a fundamental difference between a console application and a web application in this context. Is there any way to satisfy the app.manifest requirement in a web application to get long paths working again?
        • Anonymous
          January 23, 2018
          Unfortunately I'm not aware of one. You might try https://forums.asp.net/. Numerous people have been hit by the manifest "fix", hopefully we'll see a fix for the "fix" from Windows. I'll post if I see such a thing happening.
  • Anonymous
    May 03, 2017
    The comment has been removed
    • Anonymous
      May 30, 2017
      Appears to be a limitation in GetNamedSecurityInfo. Have you tried on the Creators Update (RS2)?
  • Anonymous
    June 09, 2017
    The comment has been removed
    • Anonymous
      June 10, 2017
      Sorry, don't know much about ClickOnce. :/ Windows 10 requires the manifest to allow using long paths without \?. (Note there was a bug in RS1 that didn't require the manifest.)
      • Anonymous
        June 12, 2017
        Okay, thanks. Maybe someone reading this will have solved this issue for ClickOnceHopefully, this will be turned on by default one day, without manifest manipulations :)
  • Anonymous
    July 21, 2017
    When is this going to be enabled by default? Next update 2018 maybe?
    • Anonymous
      July 22, 2017
      I don't know- I would presume not until File Explorer is fully updated for long paths. I do know the Windows teams are continuing to fill in the gaps (cmd got fixed in Creators Update for example) and that they do plan to fix File Explorer. Other underlying APIs are being fixed (such as WinRT and Shell APIs)- hopefully we'll see some of these foundational pieces in the Fall Creators Update...