Лучший способ разрешить слишком длинный путь к файлу исключение


109

Я создал приложение, которое загружает все библиотеки документов на сайте SP, но в какой-то момент оно выдает мне эту ошибку (я попытался посмотреть в Google, но ничего не нашел; теперь, если кто-то знает какой-либо трюк для решения этой проблемы, ответьте в противном случае, спасибо чтобы посмотреть на это)

System.IO.PathTooLongException: указанный путь, имя файла или оба слишком длинные. Полное имя файла должно быть меньше 260 символов, а имя каталога должно быть меньше 248 символов. в System.IO.Path.NormalizePathFast (String path, Boolean fullCheck) в System.IO.Path.GetFullPathInternal (String path) в System.IO.FileStream.Init (String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights , Общий ресурс FileShare, размер буфера Int32, параметры FileOptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, логическое значение bFromProxy) в System.IO.FileStream..ctor (путь строки, режим FileMode, доступ к FileAccess, общий ресурс FileShare, размер буфера Int32, параметры FileOptions) в System. IO.File.Create (путь к строке)

он достигает предела для строки, код приведен ниже,

#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

1
Преобразуйте путь UNC (или любой другой) в формат 8.3. [Преобразование в формат 8.3 с помощью CMD] [1] [1]: stackoverflow.com/questions/10227144/…
AutomationNation


Возможный дубликат. Здесь я нашел решение stackoverflow.com/a/44211420/5312148
Франческо

Ответы:


58

Поскольку причина ошибки очевидна, вот некоторая информация, которая должна помочь вам решить проблему:

См. Эту статью MS об именовании файлов, путей и пространств имен

Вот цитата из ссылки:

Ограничение максимальной длины пути В Windows API (за некоторыми исключениями, обсуждаемыми в следующих параграфах) максимальная длина пути составляет MAX_PATH, которая определяется как 260 символов. Локальный путь структурирован в следующем порядке: буква диска, двоеточие, обратная косая черта, компоненты имени, разделенные обратными косыми чертами, и завершающий нулевой символ. Например, максимальный путь на диске D равен «D: \ some 256-символьная строка пути <NUL>», где «<NUL>» представляет невидимый завершающий нулевой символ для текущей кодовой страницы системы. (Символы <> используются здесь для наглядности и не могут быть частью допустимой строки пути.)

И несколько обходных путей (взятых из комментариев):

Есть способы решить разные проблемы. Основная идея решений, перечисленных ниже, всегда одна и та же: уменьшить длину пути, чтобы иметь path-length + name-length < MAX_PATH. Ты можешь:

  • Поделиться подпапкой
  • Используйте командную строку, чтобы назначить букву диска с помощью SUBST
  • Используйте AddConnection в VB, чтобы назначить букву диска пути

7
@TimeToThine, вы читали статью, которую я опубликовал? Вы читали комментарии? Я могу ошибаться, но я не думаю, что вы получите дополнительную помощь от сообщества SO, кроме той, которую я уже предоставил.
Джеймс Хилл

2
Да, я уже читал это, прежде чем размещать свой вопрос здесь, я даже пробовал "\\? \", Но по какой-то причине он не работает в этом контексте. Я нахожу этот блог, использую его, но по какой-то причине он не работает должным образом " codinghorror.com/blog/2006/08/shortening-long-file-paths.html " Я все еще ищу что-то, что сохраняет каталог, и я могу взять его оттуда или что-то в этом роде, например, использовать скрытую метку для сохранения текущего каталога вместо строки, но не уверен, будет ли это работать.
Мухаммад Раджа

24
Это очевидно, но не имеет смысла. Почему есть ограничение на размер пути ??? это 2017.
Jaider

2
Если бы я изменил текущий каталог на каталог папки с помощью Directory.SetCurrentDirectory (), можно было бы избежать этого ограничения. Или проблема все еще существует.
Адам Линдси

3
Похоже, что статья была обновлена: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. но вы должны зарегистрироваться и установить раздел реестра, чтобы включить ее.
Tom Deblauwe

28

Решение, которое сработало для меня, заключалось в том, чтобы отредактировать раздел реестра, чтобы включить поведение длинного пути, установив значение 1. Это новая функция выбора для Windows 10.

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

Я получил это решение из названного раздела статьи, опубликованной @ james-hill.

https://docs.microsoft.com/windows/desktop/FileIO/naming-a-file#maximum-path-length-limitation


2
Я установил это значение в 1 и все еще получаю ошибку, не знаю почему.
Mr Angry

В статье упоминаются два требования. Во-первых, ключ реестра, а во-вторых, приложение 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>для меня в Visual Studio 2019 это второе требование не требовалось после перезапуска Visual Studio.
Том Андерсон

Извините, наверное, это глупый вопрос, но что такое "application xml"? Это web.config или что-то еще? У меня проблема на веб-странице проекта asp.net
Ондра

Как было сказано выше, он отлично работает в Visual Studio 2019 (после перезапуска) без изменения xml приложения. Спасибо за решение.
Zoman

@TomAnderson: я использую VS2017. Где я могу найти этот application.xml? поскольку после выполнения 1-го шага моя проблема не решается.
Шарад,

24

Существует библиотека под названием Zeta Long Paths, которая предоставляет .NET API для работы с длинными путями.

Вот хорошая статья, освещающая эту проблему как для .NET, так и для PowerShell: « .NET, PowerShell Path too Long Exception and a .NET PowerShell Robocopy Clone »


1
Это просто замечательно, и очень легко обновить код для его использования. Спасибо.
Артур

3

Вы можете создать символическую ссылку с более коротким каталогом. Сначала откройте командную строку, например, Shift + RightClickв нужной папке с более коротким путем (возможно, вам придется запустить ее от имени администратора).

Затем введите относительные или абсолютные пути:

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

А затем запустите Решение с более короткого пути. Преимущество здесь: вам не нужно ничего перемещать.


Это не работает в VS2015. Похоже, что VS предварительно проверяет длину пути. См. Ответ N-Ate для решения VS2015.
N-ate

1
Что вы можете сделать, так это сопоставить папку решения с драйвером с помощью команды «subst». Это работает для VS2017.
Filipe Calasans

2

В Windows 8.1 использование. NET 3.5, у меня была аналогичная проблема.
Хотя имя моего файла составляло всего 239 символов, когда я приступил к созданию экземпляра объекта FileInfo только с именем файла (без пути), произошло исключение типа 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

Я решил проблему обрезки имени файла до 204 символов (включая расширение).


Дополнительная информация для всех, кто это читает - имена файлов ограничены 247 символами, а полный путь ограничен 259. Таким образом, если ваше имя файла 239, остается только 20 символов для остальной части пути (например, "c: \ temp") . Если вы обрезаете имя файла, вам необходимо убедиться, что полный путь составляет 259 символов или меньше.
Losbear

1

Если у вас возникла проблема с вашими bin- файлами из-за длинного пути, в Visual Studio 2015 вы можете перейти на страницу свойств проблемного проекта и изменить относительный выходной каталог на более короткий.

Например, bin \ debug \ становится C: \ _ bins \ MyProject \


1
После повторного открытия свойств, когда моя сборка не удалась, я заметил, что новый путь «c: \ vs \ bin \ Release» был заменен на «.. \ .. \ .. \ .. \ .. \ .. \ .. \. . \ vs \ bin \ Release \ " . Я не уверен, что ".. \" учитывается при подсчете символов.
samis

2
Пути, которые оцениваются как слишком длинные, являются абсолютными.
Н-ели

1

Что сработало для меня, так это перемещение моего проекта, как он был на рабочем столе (C: \ Users \ lachezar.l \ Desktop \ MyFolder), в (C: \ 0 \ MyFolder), который, как вы можете видеть, использует более короткий путь и сокращение его решило проблема.


1

По моему опыту, я не буду рекомендовать приведенный ниже ответ для любых общедоступных веб-приложений.

Если он вам нужен для ваших собственных инструментов или для тестирования, я бы порекомендовал поделиться им на вашем собственном компьютере.

-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

Затем будет создан общий каталог, например \\ {PCName} \ {YourSharedRootDirectory}. Это может быть определенно намного меньше, чем ваш полный путь, я надеюсь, для меня я мог бы сократить до 30 символов с примерно 290 символов. :)


0

Не говоря уже об обновлении, есть очень хорошо налаженная библиотека для обработки слишком длинных путей. AlphaFS - это библиотека .NET, обеспечивающая более полную функциональность файловой системы Win32 для платформы .NET, чем стандартные классы System.IO. Наиболее заметным недостатком стандартного .NET System.IO является отсутствие поддержки расширенных функций NTFS, в первую очередь поддержки расширенных путей (например, пути к файлам / каталогам длиннее 260 символов).


0

Лучший ответ, который я могу найти, - в одном из комментариев здесь. Добавьте его к ответу, чтобы кто-то не пропустил комментарий и обязательно должен это попробовать. Это устранило проблему для меня.

Нам нужно сопоставить папку решения с диском с помощью команды «subst» в командной строке, например, subst z:

Затем откройте решение с этого диска (в данном случае z). Это максимально сократит путь и может решить проблему с длинным именем файла.


0

это также может быть решением. Иногда это также происходит, когда вы держите свой проект разработки слишком глубоко, значит, возможно, в каталоге проекта может быть слишком много каталогов, поэтому, пожалуйста, не создавайте слишком много каталогов, храните его в простой папке внутри диски. Например, я тоже получал эту ошибку, когда мой проект хранился вот так:

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

затем я просто вставил свой проект внутрь

D: \ Sharad \ LatestWorkings \ GenericSurveyApplication

И проблема была решена.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.