С# удаление папки с длинными путями
Я пытаюсь удалить папку, и удаление не выполняется из-за папки, содержащей длинные пути. Я предполагаю, что мне нужно использовать что-то другое вместо dir.Delete(true), кто-то пересек этот мост раньше?
Большое спасибо
try
{
var dir = new DirectoryInfo(@FolderPath);
dir.Attributes = dir.Attributes & ~FileAttributes.ReadOnly;
dir.Delete(true);
}
catch (IOException ex)
{
MessageBox.Show(ex.Message);
}
Это путь, о котором идет речь:
\ server\share\dave\Private\Careers\Карьера Ed\Fun Карьера Образование \Chris не используется 2006 to07\old 4.Careers Area Activity Неделя 1 30.10.06 или 6.11.06 или 13.11.06 Знакомство с уровнями работы и ресурсами карьеры\Профессиональные области и уровни работы Справочная информация для преподавателя [1].doc
Ответы
Ответ 1
В API Windows максимальная длина для пути - 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, который интерфейс UI оболочки не может обрабатывать.
Синтаксис С#:
[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool DeleteFile(string path);
Дополнительные сведения о классе см. В разделе " Системное пространство имен" - MSDN
Выдержки из:
Пути файловой системы: как долго слишком долго? - Ужас кодирования
Функция DeleteFile (Windows) - MSDN
Ответ 2
Лучше я до сих пор это
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();
}
}
Ответ 3
Ограничение в 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;
Ответ 4
Я не знаю, открыт ли этот вопрос, но я решил проблему. Код был разработан на машине win7 с VS2008. Это шаги, которые я предпринял для решения проблемы.
- Создать пустой проект VS С#
- Добавьте ссылку на этот COM-объект: время выполнения сценариев microsoft
- Добавить скрипт использования; в ваш список использования
-
Где-то в вашем коде создайте функцию, похожую на это:
private static void DeletePathWithLongFileNames(string path)
{
var tmpPath = @"\\?\"+ path
FileSystemObject fso = new FileSystemObjectClass() as FileSystemObject;
fso.DeleteFolder(tmpPath, true);
}
Параметр Path - это каталог, который вы хотите удалить. Функция добавляет сигнатуру пути Unicode, создает экземпляры FileSystemObject и удаляет путь unicode и все его содержимое.
- Скомпилируйте программу, запустите полученные .exe файлы с правами администратора (запустите как Administrator на win7), найдите каталог, который вы хотите удалить, и примените к нему эту функцию. Затем просмотрите длинные имена файлов.
Излишне говорить, что это мощно... и опасно. С большой силой приходит большая ответственность:-)
Ответ 5
Это то, что я использую для удаления домашних каталогов, где часто встречаются длинные пути:
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 завершится с ошибкой на все, что помечено как только для чтения.
- Создает уникальное имя пустого каталога, поэтому оно работает с несколькими потоками.
Ответ 6
Проверьте API Win32: http://msdn.microsoft.com/en-us/library/aa363915%28VS.85%29.aspx
Там говорится: "В версии ANSI этой функции имя ограничено символами MAX_PATH. Чтобы расширить этот предел до 32 767 символов, вызовите версию функции Unicode и добавьте" \?\ "к пути".
Добавьте pinvoke:
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);
}
Ответ 7
Вы можете попробовать использовать p/invoke для захвата "короткого" имени пути с помощью функции GetShortPathName из файла kernel32.dll:
http://www.pinvoke.net/default.aspx/kernel32.GetShortPathName
Ответ 8
В следующей ссылке показана внутренняя реализация .NET для поддержки длинного пути в System.IO, она не самая легкая для чтения, созданная с помощью Reflector, но содержит множество примеров работы с API-интерфейсами Win32, упомянутых ранее.
http://reflector.webtropy.com/default.aspx/[email protected]/[email protected]/untmp/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/clr/src/BCL/System/IO/[email protected]/1305376/[email protected]
Было бы неплохо, если бы эта функция была доступна через System.IO, так как поддержка там явно!
Ответ 9
Я создал управляемую библиотеку .Net для работы с файлами и папками.
https://github.com/DotNetIO
var fs = LocalFileSystem.Instance : FileSystem
^^^^ место в IoC
fs.GetDirectory(@"C:\\a very very long path ...\with\subdirs\and files.txt").Delete();
Приветствия