PathTooLongException C# 4.5
У меня проблемы с копированием некоторых папок с 260+ символами (например, F:\NNNNNNNNNNNNNNNN\ NNNNNNNNNNNN\ROOT\$RECYCLE.BIN\S-1-5-21-3299053755-4209892151-505108915-1000\$RMSL3UNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN NNNNNNNNNNN\NNNNNNNNNN\NNNNNNNNNN\publish\ Файлы приложений \TNNNNNNNNNNNN_1_0_0_0\NNNNNNNNNNNN.exe.manifest) в другое место со стандартным DrectoryInfo.Create); добавление \?\ или \?\UNC\ (например, "\\?\UNC\") просто вызывает другое ArgumentException. Что я делаю неправильно? Что еще я могу сделать без использования Directory.SetCurrentDirectory()?
3 ответа
Да, использование стандартных API предоставит вам такие ограничения (255 символов IIRC).
Из.NET вы можете использовать проект AlphaFS, который позволяет вам использовать очень длинные пути (используя стиль \\?\") И имитирует пространство имен System.IO.
Вы, вероятно, сможете использовать эту библиотеку так же, как если бы вы использовали System.IO, например: AlphaFS.Win32.Filesystem.File.Copy () вместо System.IO.File.Copy ()
Если вы не хотите или не можете использовать AlphaFS, вам придется пробить Win32 API
В Microsoft TechNet есть отличная библиотека для преодоления проблемы длинных имен файлов, она называется Delimon.Win32.I O Library (V4.0) и имеет свои собственные версии ключевых методов из System.IO.
Например, вы бы заменили:
System.IO.Directory.GetFiles
с
Delimon.Win32.IO.Directory.GetFiles
что позволит вам обрабатывать длинные файлы и папки.
С веб-сайта:
Delimon.Win32.IO заменяет основные файловые функции System.IO и поддерживает имена файлов и папок длиной до 32 767 символов.
Эта библиотека написана на.NET Framework 4.0 и может использоваться в системах x86 и x64. Ограничения "Файл и папка" стандартного пространства имен System.IO могут работать с файлами, содержащими 260 символов в имени файла и 240 символов в имени папки (MAX_PATH обычно настраивается как 260 символов). Обычно вы сталкиваетесь с ошибкой System.IO.PathTooLongException со стандартной библиотекой.NET.
На самом деле вам нужно позвонить в Win32 из C#. Мы сделали это
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;
public static class LongPath
{
static class Win32Native
{
[StructLayout(LayoutKind.Sequential)]
public class SECURITY_ATTRIBUTES
{
public int nLength;
public IntPtr pSecurityDescriptor;
public int bInheritHandle;
}
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool CreateDirectory(string lpPathName, SECURITY_ATTRIBUTES lpSecurityAttributes);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern SafeFileHandle CreateFile(string lpFileName, int dwDesiredAccess, FileShare dwShareMode, SECURITY_ATTRIBUTES securityAttrs, FileMode dwCreationDisposition, int dwFlagsAndAttributes, IntPtr hTemplateFile);
}
public static bool CreateDirectory(string path)
{
return Win32Native.CreateDirectory(String.Concat(@"\\?\", path), null);
}
public static FileStream Open(string path, FileMode mode, FileAccess access)
{
SafeFileHandle handle = Win32Native.CreateFile(String.Concat(@"\\?\", path), (int)0x10000000, FileShare.None, null, mode, (int)0x00000080, IntPtr.Zero);
if (handle.IsInvalid)
{
throw new System.ComponentModel.Win32Exception();
}
return new FileStream(handle, access);
}
}
Пример кода:
string path = @"c:\".PadRight(255, 'a');
LongPath.CreateDirectory(path);
path = String.Concat(path, @"\", "".PadRight(255, 'a'));
LongPath.CreateDirectory(path);
string filename = Path.Combine(path, "test.txt");
FileStream fs = LongPath.Open(filename, FileMode.CreateNew, FileAccess.Write);
using (StreamWriter sw = new StreamWriter(fs))
{
sw.WriteLine("abc");
}