Найкращий спосіб вирішити занадто довгий виняток шляху до файлу


109

Я створив додаток, який завантажує всі бібліотеки документів на веб-сайті SP, але в один момент він видав мені цю помилку (я спробував подивитися на google, але не міг; нічого не знайду. Тепер, якщо хтось знає який-небудь трюк, щоб вирішити цю проблему, будь ласка, відповідь інакше дякую для перегляду)

System.IO.PathTooLongException: Зазначений шлях, ім'я файлу або обидва вони занадто довгі. Повноцінне ім'я файлу повинно бути менше 260 символів, а ім'я каталогу - менше 248 символів. на System.IO.Path.NormalizePathFast (Шлях рядка, булева програма FullCheck) на System.IO.Path.GetFullPathInternal (Штриховий шлях) на System.IO.FileStream.Init (Штриховий шлях, режим FileMode, доступ до FileAccess, права Int32, булева використанняRights , Поділка файлів, Int32 bufferSize, параметри FileOptions, SECURITY_ATTRIBUTES secAttrs, String msgPath, булева bFromProxy) на System.IO.FileStream..ctor (Строковий шлях, режим FileMode, доступ до FileAccess, папка FileShare, Int32 bufferSize, параметри FileOptions). 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 про іменування файлів, шляхів та просторів імен

Ось цитата за посиланням:

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

І кілька обхідних шляхів (взяті з коментарів):

Існують способи вирішення різних проблем. Основна ідея перелічених нижче рішень завжди однакова: зменшіть довжину шляху, щоб мати path-length + name-length < MAX_PATH. Ви можете:

  • Поділитися підпапками
  • Використовуйте командний рядок, щоб призначити літеру диска за допомогою SUBST
  • Використовуйте AddConnection в VB, щоб призначити букву диска шляху

7
@TimeToThine, ти читав статтю, яку я опублікував? Ви читали коментарі? Я можу помилятися, але я не думаю, що ви більше не отримаєте допомоги від спільноти ОЗ, окрім тієї, яку я вже надав.
Джеймс Гілл

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

24
Це очевидно, але це не має ніякого сенсу. Чому існує обмеження розміру шляху ??? це 2017.
Джайдер

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

3
Стаття, здається, була оновлена: Starting in Windows 10, version 1607, MAX_PATH limitations have been removed from common Win32 file and directory functions. Але ви повинні увімкнути та встановити ключ реєстру, щоб це ввімкнути.
Том Деблауве

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 і все ще отримує помилку, не маю уявлення, чому в цей момент.
Містер Злий

У статті згадуються дві вимоги. По-перше, ключ реєстру, а по-друге додаток 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.
Том Андерсон

Вибачте, напевно, це дурне питання, але що таке "додаток xml"? Це web.config чи щось інше? У мене ця проблема є на веб-сторінці проекту asp.net
Ондра Старенко

Як було сказано вище, він працює чудово у Visual Studio 2019 (після перезавантаження) без зміни програми xml. Дякую за рішення.
Зоман

@TomAnderson: Я використовую VS2017. Де я можу знайти це application.xml? так як після 1-го кроку моя проблема не вирішує.
Шарад

23

Існує бібліотека під назвою Zeta Long Paths, яка забезпечує API .NET для роботи з довгими шляхами.

Ось хороша стаття, яка висвітлює цю проблему як для .NET, так і для PowerShell: " .NET, PowerShell Path занадто довгий виняток і .NET Robocopy клон PowerShell ".


1
Тепер це просто чудово, і дійсно легко оновити код для його використання. Дякую.
Артур

3

Можна створити символічне посилання за допомогою коротшого каталогу. Перший відкритий командний рядок, наприклад, відShift + RightClick у потрібній папці зі скороченим шляхом (можливо, вам доведеться запустити його як адміністратор).

Потім введіть відносні або абсолютні шляхи:

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

А потім почніть Розв’язання з коротшого шляху. Перевага тут полягає в тому, що вам нічого не потрібно рухати.


Це не працює в VS2015. Здавалося б, VS переважає по довжині шляху. Дивіться відповідь N-Ate для обходу VS2015.
N-ate

1
Що ви можете зробити, це зіставити папку рішення на драйвер за допомогою команди "subst". Це працює для VS2017.
Філіпе Калазанс

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 символів або менше.
Лосбер

1

Якщо у вас виникають проблеми з бін- файлами через довгий шлях, у Visual Studio 2015 ви можете перейти на сторінку властивостей проекту, що порушує правопорушення, і змінити відносну каталогіку виводу на більш коротку.

Напр. Bin \ debug \ стає C: \ _ bins \ MyProject \


1
Після повторного відкриття властивостей, коли моя збірка не вдалася, я помітив, що новий шлях "c: \ vs \ bin \ Release" був замінений на ".. \ .. \ .. \ .. \ .. \ .. \ .. \ .. \. . \ vs \ bin \ Відпустіть \ " . Я не впевнений, чи ".. \" стане враховано до кількості символів.
Саміс

2
Шляхи, які оцінюються як занадто довгі, є абсолютними шляхами.
N-ate

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.