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