Альтернатива Directory.CreateDirectory(path), поддерживающая длинные пути

Просто интересно, есть ли альтернатива Directory.CreateDirectory() я пытаюсь создать каталог длиной более 260 символов, хотя имя файла не длинное, а путь к каталогу.

ИЛИ ЖЕ

Если есть какой-то трюк, используя который я могу указать CreateDirectory создать папку в этом месте без указания полного пути к каталогу. Поскольку я создаю папки внутри папок и так далее. Должен быть какой-то законный способ сделать это.

Возникла проблема со строкой, которую я сейчас сохранил в скрытом ярлыке, так что это больше не проблема.

4 ответа

Решение

Простое решение состоит в том, чтобы использовать unc-включенный путь, который будет позволять пути к файлам приблизительно до 32767 символов

string longPathEnabledFileName = Path.ToLongPath("C:\SomeVeryLongPath\...."); 
FileStream fs = new FileStream(longPathEnabledFileName);

Это просто добавит путь к \\?\, Что говорит каркасу обойти ограничение MAX_PATH в 260 символов. К сожалению, префикс \\?\ Не поддерживается в.Net на момент написания (начиная с версии 4.0)

Это оставляет нам решение WinApi и ссылку Kernel32.dll на использование SafeFileHandle. Ким Хэмилтон из команды BCL опубликовал здесь серию обходных путей к ограничениям MAX_PATH (часть 2 показывает, как использовать функции winapi) с фрагментом кода, включенным здесь для справки:

// Этот фрагмент кода предоставляется в рамках разрешающей лицензии Microsoft.
используя Систему;
используя System.IO;
using System.Runtime.InteropServices;
использование Microsoft.Win32.SafeHandles;

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
внутренний статический extern SafeFileHandle CreateFile(строка lpFileName,
    EFileAccess dwDesiredAccess,
    EFileShare dwShareMode,
    IntPtr lpSecurityAttributes,
    ECreationDisposition dwCreationDisposition,
    EFileAttributes dwFlagsAndAttributes,
    IntPtr hTemplateFile);

public static void TestCreateAndWrite(строка fileName) {

    string formattedName = @"\\?\" + fileName;
    // Создать файл с общим доступом для записи
    SafeFileHandle fileHandle = CreateFile(formattedName,
        EFileAccess.GenericWrite, EFileShare.None, IntPtr.Zero,
        ECreationDisposition.CreateAlways, 0, IntPtr.Zero);

    // Проверка на ошибки
    int lastWin32Error = Marshal.GetLastWin32Error();
    if (fileHandle.IsInvalid) {
        бросить новый System.ComponentModel.Win32Exception(lastWin32Error);
    }

    // Передаем дескриптор файла в FileStream. FileStream закроет
    // справиться
    используя (FileStream fs = new FileStream (fileHandle,
                                    FileAccess.Write)) {
        fs.WriteByte (80);
        fs.WriteByte (81);
        fs.WriteByte (83);
        fs.WriteByte (84);
    }
}

Существует также библиотека, которая инкапсулирует всю эту работу в коде Google, которая называется "Зета длинные пути".

Установите каталог как текущий и создайте каталог в нем.

 Directory.SetCurrentDirectory(@"c:\sample");
 Directory.CreateDirectory("test");

Альтернативный способ - использование DirectoryInfo класс и метод DirectoryInfo.Create,

Я не пробовал, но MSDN показывает, что это не исключение, если вы используете слишком длинный путь.

РЕДАКТИРОВАТЬ:

Также я нашел кое-что, что может помочь вам решить вашу проблему. Посмотрите на этот код

Как насчет разделения вашего предполагаемого пути с помощью символа '\', затем циклически проходя по каждому элементу, проверяя, существует ли каталог, если нет - создайте его, а затем используйте

Directory.SetCurrentDirectory(directoryName);
Другие вопросы по тегам