Best way to resolve file path too long exception
Asked Answered
W

13

137

I created a app that downloads all document libraries in a SP Site , but at one point it giving me this error (I tried looking at google but couldn;t find anything, now if anyone knows any trick to solve this problem please respond otherwise thanks for looking at it)

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.Path.NormalizePathFast(String path, Boolean fullCheck) at System.IO.Path.GetFullPathInternal(String path) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) at System.IO.File.Create(String path)

it reaches the limit for string, Code is given below,

#region Downloading Schemes

    private void btnDownload_Click(object sender, EventArgs e)
    {
        TreeNode currentNode = tvWebs.SelectedNode;
        SPObjectData objectData = (SPObjectData)currentNode.Tag;
        try
        {
            CreateLoggingFile();
            using (SPWeb TopLevelWeb = objectData.Web)
            {
                if(TopLevelWeb != null)
                    dwnEachWeb(TopLevelWeb, TopLevelWeb.Title, tbDirectory.Text);
            }
        }
        catch (Exception ex)
        {
            Trace.WriteLine(string.Format("Exception caught when tried to pass TopLevelWeb:{1}, Title = {2}, object data to (dwnEachWeb_method), Exception: {0}", ex.ToString(), objectData.Web, objectData.Title));
        }
        finally
        {
            CloseLoggingFile();
        }
    }

    private void dwnEachWeb(SPWeb TopLevelWeb, string FolderName, string CurrentDirectory)
    {
        if (TopLevelWeb != null)
        {
            if (TopLevelWeb.Webs != null)
            {
                CurrentDirectory = CurrentDirectory + "\\" + TopLevelWeb.Title;
                CreateFolder(CurrentDirectory);
                foreach (SPWeb ChildWeb in TopLevelWeb.Webs)
                {

                    dwnEachWeb(ChildWeb, ChildWeb.Title, CurrentDirectory);
                    ChildWeb.Dispose();
                }
                dwnEachList(TopLevelWeb, CurrentDirectory);
                //dwnEachList(TopLevelWeb, FolderName, CurrentDirectory);
            }
        }
    }

    private void dwnEachList(SPWeb oWeb, string CurrentDirectory)
    {
        foreach (SPList oList in oWeb.Lists)
        {
            if (oList is SPDocumentLibrary && !oList.Hidden)
            {
                dwnEachFile(oList.RootFolder, CurrentDirectory);
            }
        }
    }

    private void dwnEachFile(SPFolder oFolder, string CurrentDirectory)
    {
        if (oFolder.Files.Count != 0)
        {
            CurrentDirectory = CurrentDirectory + "\\" + oFolder.Name;
            CreateFolder(CurrentDirectory);
            foreach (SPFile ofile in oFolder.Files)
            {
                if (CreateDirectoryStructure(CurrentDirectory, ofile.Url))
                {
                    var filepath = System.IO.Path.Combine(CurrentDirectory, ofile.Url);
                    byte[] binFile = ofile.OpenBinary();
                    System.IO.FileStream fstream = System.IO.File.Create(filepath);
                    fstream.Write(binFile, 0, binFile.Length);
                    fstream.Close();
                }
            }
        }
    }

    //creating directory where files will be download        
    private bool CreateDirectoryStructure(string baseFolder, string filepath)
    {
        if (!Directory.Exists(baseFolder)) return false;

        var paths = filepath.Split('/');

        for (var i = 0; i < paths.Length - 1; i++)
        {
            baseFolder = System.IO.Path.Combine(baseFolder, paths[i]);
            Directory.CreateDirectory(baseFolder);
        }
        return true;
    }

    //creating folders
    private bool CreateFolder(string CurrentDirectory)
    {
        if (!Directory.Exists(CurrentDirectory))
        {
            Directory.CreateDirectory(CurrentDirectory);
        }
        return true;
    }

    //shorting string

    #endregion
Workwoman answered 5/1, 2012 at 15:39 Comment(3)
Convert the UNC (or whatever) path into an 8.3 format. [Convert to 8.3 format using CMD][1] [1]: #10227644Pre
Possible duplicate of How to avoid System.IO.PathTooLongException?Springclean
Possible duplicate. Here I found out the solution https://mcmap.net/q/168474/-any-way-to-work-around-the-pathtoolongexception-that-filesysteminfo-fullname-throws-sometimesGantz
T
70

As the cause of the error is obvious, here's some information that should help you solve the problem:

See this MS article about Naming Files, Paths, and Namespaces

Here's a quote from the link:

Maximum Path Length Limitation In the Windows API (with some exceptions discussed in the following paragraphs), the maximum length for a path is MAX_PATH, which is defined as 260 characters. A local path is structured in the following order: drive letter, colon, backslash, name components separated by backslashes, and a terminating null character. For example, the maximum path on drive D is "D:\some 256-character path string<NUL>" where "<NUL>" represents the invisible terminating null character for the current system codepage. (The characters < > are used here for visual clarity and cannot be part of a valid path string.)

And a few workarounds (taken from the comments):

There are ways to solve the various problems. The basic idea of the solutions listed below is always the same: Reduce the path-length in order to have path-length + name-length < MAX_PATH. You may:

  • Share a subfolder
  • Use the commandline to assign a drive letter by means of SUBST
  • Use AddConnection under VB to assign a drive letter to a path
Tanka answered 5/1, 2012 at 15:44 Comment(6)
@TimeToThine, did you read the article that I posted? Did you read the comments? I could be wrong, but I don't think you're going to get any more help from the SO community, other than what I've already provided.Tanka
Yes I already read that before posting my question here, I even tried "\\?\" but for some reason its not working in this context. I find this blog, using it but for some reason its not working properly, "codinghorror.com/blog/2006/08/shortening-long-file-paths.html" Am still looking for something that keeps the directory saved and i can take it from there, or something like that, forexample use a hidden label to save the current directory instead of string, but not sure if it will gonna work.Workwoman
It is obvious but it doesn't make any sense. Why is there a path-size limitation??? it is 2017.Ruyter
If I changed the current directory to the directory of the folder using Directory.SetCurrentDirectory() would it avoid this restriction. Or would the problem still exist.Anguished
The article seems to have been updated: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. But you must opt-in, and set a registry key to enable it.Terryl
This solution seems to still work. tested on VS2017 v15.7.6Bradfield
L
59

The solution that worked for me was to edit the registry key to enable long path behaviour, setting the value to 1. This is a new opt-in feature for Windows 10

HKLM\SYSTEM\CurrentControlSet\Control\FileSystem LongPathsEnabled (Type: REG_DWORD)

I got this solution from a named section of the article that @james-hill posted.

Naming Files, Paths, and Namespaces: Maximum Path Length Limitation

In editions of Windows before Windows 10 version 1607, the maximum length for a path is MAX_PATH, which is defined as 260 characters. In later versions of Windows, changing a registry key or using the Group Policy tool is required to remove the limit. See Maximum Path Length Limitation for full details.


See also Maximum Path Length Limitation mentioned by @dontbyteme.

To enable the new long path behavior, both of the following conditions must be met:

  • The registry key Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled (Type: REG_DWORD) must exist and be set to 1. The key's value will be cached by the system (per process) after the first call to an affected Win32 file or directory function (see below for the list of functions). The registry key will not be reloaded during the lifetime of the process. In order for all apps on the system to recognize the value of the key, a reboot might be required because some processes may have started before the key was set.
  • The application manifest must also include the longPathAware element.
<application xmlns="urn:schemas-microsoft-com:asm.v3">
   <windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
       <ws2:longPathAware>true</ws2:longPathAware>
   </windowsSettings>
</application>
Linalool answered 12/10, 2018 at 11:41 Comment(7)
I've got this set to 1 and still getting the error, no idea why at this point.Commodus
The article mentions two requirements. Firstly the registry key, and secondly the application xml: <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings xmlns:ws2="https://schemas.microsoft.com/SMI/2016/WindowsSettings"> <ws2:longPathAware>true</ws2:longPathAware> </windowsSettings> </application> For me in Visual Studio 2019, this second requirement was not necessary after restarting Visual Studio.Agathaagathe
I'm sorry probably this is stupid question but What is "application xml"? Is it web.config or something else? I have this problem on Web Page asp.net projectCeratodus
As said above, it works fine in Visual Studio 2019 (after restart) without changing the application xml. Thanks for the solution.Solidary
@TomAnderson : I am using VS2017. Where iI can find this application.xml ? as after doing 1st step does not solve my problem.Kilmer
@OndraStarenko The xml is in the application manifest file. See Application Manifests for more info. You'll need to add the longPathAware to your application's manifest file. For example, If you open PowerShell.exe from your C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe in Visual Studio, you can view the application manifest. And see this setting inside the exe.Quagga
Link to further details mentioned by Tom Anderson: learn.microsoft.com/de-de/windows/win32/fileio/…Isologous
P
26

There's a library called Zeta Long Paths that provides a .NET API to work with long paths.

Here's a good article that covers this issue for both .NET and PowerShell: ".NET, PowerShell Path too Long Exception and a .NET PowerShell Robocopy Clone"

Parsaye answered 13/1, 2013 at 19:1 Comment(1)
Now this is just wonderful, and really easy to update the code for using it. Thanks.Algicide
C
9

You can create a symbolic link with a shorter directory. First open command line for example by Shift + RightClick in your desired folder with a shorter path (you may have to run it as administrator).

Then type with relative or absolute paths:

mklink ShortPath\To\YourLinkedSolution C:\Path\To\Your\Solution /D

And then start the Solution from the shorter path. The advantage here is: You don't have to move anything.

Chew answered 17/6, 2017 at 10:11 Comment(3)
This doesn't work in VS2015. It would appear that VS is prevalidating the length of the path. See N-Ate answer for VS2015 work-around.Xanthe
What you can do is to map the solution folder to a driver using the command "subst". That works for VS2017.Foretopsail
Much simpler and more objective. Thanks!Entropy
G
5

What worked for me is moving my project as it was on the desktop (C:\Users\lachezar.l\Desktop\MyFolder) to (C:\0\MyFolder) which as you can see uses shorter path and reducing it solved the problem.

Grammar answered 22/6, 2018 at 14:23 Comment(0)
A
2

On Windows 8.1, using. NET 3.5, I had a similar problem.
Although the name of my file was only 239 characters length when I went to instantiate a FileInfo object with just the file name (without path) occurred an exception of type System. IO.PathTooLongException

2014-01-22 11:10:35 DEBUG LogicalDOCOutlookAddIn.LogicalDOCAddIn - fileName.Length: 239 
2014-01-22 11:10:35 ERROR LogicalDOCOutlookAddIn.LogicalDOCAddIn - Exception in ImportEmail System.IO.PathTooLongException: Percorso e/o nome di file specificato troppo lungo. Il nome di file completo deve contenere meno di 260 caratteri, mentre il nome di directory deve contenere meno di 248 caratteri.
   in System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
   in System.IO.FileInfo..ctor(String fileName)
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.GetTempFilePath(String fileName) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 692
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmail(_MailItem mailItem, OutlookConfigXML configXML, Int64 targetFolderID, String SID) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 857
   in LogicalDOCOutlookAddIn.LogicalDOCAddIn.ImportEmails(Explorers explorers, OutlookConfigXML configXML, Int64 targetFolderID, Boolean suppressResultMB) in C:\Users\alle\Documents\Visual Studio 2010\Projects\MyAddin1Outlook20072010\MyAddin1Outlook20072010\LogicalDOCAddIn.cs:riga 99

I resolved the problem trimming the file name to 204 characters (extension included).

Accouter answered 22/1, 2014 at 10:39 Comment(1)
Additional info for anyone who reads this - Filenames are limited to 247 characters while the full path is limited to 259. So if your filename is 239, that only leaves 20 characters for the rest of the path (eg "c:\temp"). If you trim the filename, you need to make sure the FULL path is 259 characters or less.Fields
X
2

If you are having an issue with your bin files due to a long path, In Visual Studio 2015 you can go to the offending project's property page and change the relative Output Directory to a shorter one.

E.g. bin\debug\ becomes C:\_bins\MyProject\

Xanthe answered 12/3, 2018 at 19:44 Comment(2)
After re-opening properties when my build failed I noticed the new path "c:\vs\bin\Release" was substituted as "..\..\..\..\..\..\..\..\vs\bin\Release\". I'm not sure if "..\" gets factored into character count.Drifter
Paths that are evaluated as too long are absolute paths.Xanthe
E
2

Not mention so far and an update, there is a very well establish library for handling paths that are too long. AlphaFS is a .NET library providing more complete Win32 file system functionality to the .NET platform than the standard System.IO classes. The most notable deficiency of the standard .NET System.IO is the lack of support of advanced NTFS features, most notably extended length path support (eg. file/directory paths longer than 260 characters).

Embankment answered 25/2, 2019 at 16:7 Comment(0)
B
0

The best answer I can find, is in one of the comments here. Adding it to the answer so that someone won't miss the comment and should definitely try this out. It fixed the issue for me.

We need to map the solution folder to a drive using the "subst" command in command prompt- e.g., subst z:

And then open the solution from this drive (z in this case). This would shorten the path as much as possible and could solve the lengthy filename issue.

Begin answered 30/4, 2019 at 5:47 Comment(0)
W
0

From my experience, won't recommend my below answer for any public facing Web applications.

If you need it for your inhouse tools or for Testing, I would recommend to share it on your own machine.

-Right click on the root path you need to access
-Choose Properties
-Click on Share button and add your chosen users who can access it

This will then create a shared directory like \\{PCName}\{YourSharedRootDirectory} This could be definitely much less than your full path I hope, for me I could reduce to 30 characters from about 290 characters. :)

Waves answered 15/7, 2019 at 16:48 Comment(0)
T
0

this may be also possibly solution.It some times also occurs when you keep your Development project into too deep, means may be possible project directory may have too many directories so please don't make too many directories keep it in a simple folder inside the drives. For Example- I was also getting this error when my project was kept like this-

D:\Sharad\LatestWorkings\GenericSurveyApplication020120\GenericSurveyApplication\GenericSurveyApplication

then I simply Pasted my project inside

D:\Sharad\LatestWorkings\GenericSurveyApplication

And Problem was solved.

Tyranny answered 7/1, 2020 at 6:1 Comment(0)
A
0

Apps that target the .NET Framework 4.6.2 and later versions Long paths are supported by default. The runtime throws a PathTooLongException under the following conditions:

  • The operating system returns COR_E_PATHTOOLONG or its equivalent.
  • The length of the path exceeds Int16.MaxValue (32,767) characters.

https://learn.microsoft.com/en-us/dotnet/api/system.io.pathtoolongexception?view=net-6.0

Aarau answered 27/1, 2022 at 9:13 Comment(0)
M
0

The folowing worked with me on Windows 10 using visual studio 2022 :

run the following powershell script :

New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" ` -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force

restart your pc and run visual studio again.

if you dont want to change the registery move the project to a shorter path destination.

Madelon answered 13/6, 2023 at 15:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.