Питання C # видалення папки з довгими шляхами


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

Велике дякую

 try
{
 var dir = new DirectoryInfo(@FolderPath);
 dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly;
 dir.Delete(true);
}
catch (IOException ex)
{
 MessageBox.Show(ex.Message);
}

Це шлях, про який йде мова: \ Сервер \ обмін \ Дейв \ Приватний \ Кар'єра \ Кар'єра Ed \ Fun Кар'єра Освіта \ Chris не використовувався 2006 р. до07 \ old 4.Careers Area Activity Week 1 30.10.06 або 6.11.06 або 13.11.06 Введення в ресурси та кар'єрні ресурси \ Професійні сфери та рівні роботи Довідкова сторінка Tutor [1]. Doc


14
2018-02-08 16:19


походження


Скільки довгих шляхів: codinghorror.com/blog/archives/000729.html - James Campbell
Ви спробували виклик функції win32 з унікальним шляхом? - sclarson


Відповіді:


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

Версії багатьох функцій Unicode дозволяють встановити максимальну довжину шляху приблизно 32 000 символів, що складається з компонентів довжиною до 255 символів. Щоб вказати цей шлях, використовуйте "\\?\" префікс Максимальний шлях до 32 000 символів приблизний, тому що "\\?\" префікс може бути розширений на довший рядок, а розширення застосовується до загальної довжини.

Наприклад, "\\?\D:\<path>". Щоб вказати такий шлях UNC, використовуйте "\\?\UNC\" префікс Наприклад, "\\?\UNC\<server>\<share>". Ці префікси не використовуються як частина самого шляху. Вони вказують на те, що шлях повинен бути переданий системі з мінімальною модифікацією, а це означає, що ви не можете використовувати прямі косу риси, щоб представляти розділювачі шляху, або період для представлення поточного каталогу. Також ви не можете використовувати "\\?\" префікс з відносним шляхом. Відносні шляхи обмежуються MAX_PATH символами.

Оболонка та файлова система можуть мати різні вимоги. Можна створити шлях з API, який неможливо виконати з інтерфейсом оболонки.

Синтаксис C #:

[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool DeleteFile(string path);

Для отримання додаткової інформації про клас див Простір імен System - MSDN

Витяги з:

Шляхи файлової системи: скільки часу забагато? - Кодування жахів

Функція DeleteFile (Windows) - MSDN


9
2018-02-08 16:24



Привіт, я просто спробував це, і я отримав таку саму помилку "Не вдалося знайти частину шляху" довгий шлях і ім'я файлу "". Чи знаєте ви про щось, що я можу спробувати? Дякую - Jamie
Це працює, я спробував це, працює на 300 символів довжиною для мене. - James Campbell
Це не \? \, Це \\? \. - Henrik


Краще, що я поки що це робив

public static class IOHelper
{
    public static void DeleteDirectory(DirectoryInfo directoryInfo)
    {
        var emptyTempDirectory = new DirectoryInfo(Path.Combine(Path.GetTempPath(), "IOHelperEmptyDirectory"));
        emptyTempDirectory.Create();
        var arguments = string.Format("\"{0}\" \"{1}\" /MIR", emptyTempDirectory.FullName, directoryInfo.FullName);
        using (var process = Process.Start(new ProcessStartInfo("robocopy")
                                            {
                                                Arguments = arguments,
                                                CreateNoWindow = true,
                                                UseShellExecute = false,
                                            }))
        {
            process.WaitForExit();
        }
        directoryInfo.Delete();
    }
}

4
2017-10-21 06:05



Було б добре, якщо ви поясните, що таке робокопія і чому ви використовуєте / MIR - Vinicius Rocha


Обмеження на 260 символів (я вважаю, це той, з яким ви працюєте) - це проблема в Windows, а не в .NET, на жаль, тому робота навколо неї може бути складною.

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

тобто:

var curDir = Directory.GetCurrentDirectory();
Environment.CurrentDirectory = @"C:\Part\Of\The\Really\Long\Path";
Directory.Delete("Relative\Path\To\Directory");
Environment.CurrentDirectory = curDir;

3
2018-02-08 16:38



у вас відсутній @ в Directory.Delete ("Відносний \ Path \ To \ Directory"); - Simon
і це, здається, не працює - Simon


Я не знаю, чи це питання все ще відкрите, але я вирішив цю проблему. Код був розроблений на машині win7, з VS2008. Це кроки, які я використав, щоб вирішити проблему

  1. Створіть порожній проект VS C #
  2. Додайте посилання на цей COM-об'єкт: Microsoft скриптизація виконання
  3. Додати сценарію за допомогою; до вашого списку використання
  4. Десь у вашому коді створіть функцію, яка схожа на це:

    private static void DeletePathWithLongFileNames(string path)
    {
        var tmpPath = @"\\?\"+ path
        FileSystemObject fso = new FileSystemObjectClass() as FileSystemObject;
        fso.DeleteFolder(tmpPath, true); 
    }
    

Параметр Шлях - це каталог, який потрібно видалити. Функція задається підписом шляху Unicode, створює екземпляри FileSystemObject та видаляє Unicode шлях і весь його зміст.

  • Скомпілюйте програму, запустіть отримані файли .exe з правами адміністратора (запустіть адміністратора на win7), знайдіть каталог, який хочете видалити, і застосуйте цю функцію на ньому. Потім дивіться довгі імена файлів.

Зрозуміло, це потужно ... і небезпечно. З великою силою приходить велика відповідальність :-)


3
2017-12-21 10:09





Це те, що я використовую для видалення домашніх каталогів, де часто трапляються довгі шляхи:

public static void DirectoryDeleteLong(string directoryPath)
{
    var emptyDirectory = new DirectoryInfo(Path.GetTempPath() + "\\TempEmptyDirectory-" + Guid.NewGuid());
    try
    {
        emptyDirectory.Create();
        using (var process = new Process())
        {
            process.StartInfo.FileName = "robocopy.exe";
            process.StartInfo.Arguments = "\"" + emptyDirectory.FullName + "\" \"" + directoryPath + "\" /mir /r:1 /w:1 /np /xj /sl";
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.CreateNoWindow = true;
            process.Start();
            process.WaitForExit();
        }
        emptyDirectory.Delete();
        new DirectoryInfo(directoryPath).Attributes = FileAttributes.Normal;
        Directory.Delete(directoryPath);
    }
    catch(IOException) { }
}

Це схоже на рішення, яке виклав Саймон, але також:

  • Знижує високий рівень повтору скарбів robocopy.
  • Скидає атрибути як directory.delete не вдасться на щось, позначене як прочитане.
  • Створює унікальне пусте ім'я каталогу, таким чином він працює з декількома потоками.

2
2017-10-19 13:53





Перевірте Win32 API: http://msdn.microsoft.com/en-us/library/aa363915%28VS.85%29.aspx 

У ній зазначено: "У ANSI-версії цієї функції ім'я обмежене символами MAX_PATH. Щоб збільшити цей ліміт до 32 767 широких символів, зателефонувати на версію функції Unicode і додати" \? \ "До шляху".

Додайте піньок:

using System;  
using System.Runtime.InteropServices;  
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)]  
[return: MarshalAs(UnmanagedType.Bool)]  
internal static extern bool DeleteFile(string lpFileName);

Використай це:

public static void DeleteLong(string fileName) {

    string LongName = @"\\?\" + fileName;
    DeleteFile(formattedName);
}

1
2018-02-08 16:48



Починаючи з Windows 10 версії 1607 для унікальної версії цієї функції (DeleteFileW), ви можете вибрати, щоб видалити обмеження символів MAX_PATH без додавання "\\? \". Див. Розділ "Максимальний шлях обмеження" в розділі Назви файлів, шляхів та просторів імен для деталей. - JJS
The DeleteFile() API працює на файлах, а не на каталогах. RemoveDirectory() це правильний API. - linuxuser27


Ви можете спробувати скористатися p / invoke, щоб захопити назву шляху "короткого", використовуючи функцію GetShortPathName з kernel32.dll:

http://www.pinvoke.net/default.aspx/kernel32.GetShortPathName


0
2018-02-08 16:41