Вибираємо довгий шлях (або прощавай MAX_PATH)



Багатьом користувачам ПК під управлінням ОС Windows, не кажучи про розробників, знайомі проблеми при роботі з довгими (більше 260 символів, MAX_PATH) шляхами файлів або каталогів.

У даній статті розглядаються способи позбавлення від цього пережитку при розробці додатків на різних платформах (WinApi, .Net Framework .Net Core) і активації нативної підтримки довгих шляхів у Windows 10 (Anniversary Update).

Програми Win API

В додатках, які використовують Win API для роботи з файлами, рецепт порятунку від обмеження MAX_PATH був відомий з незапам'ятних часів – необхідно було використовувати Unicode версію функції з закінченням «W» для роботи з директорією або файлом і починати дорогу з префікса \\?\. Це давало можливість використовувати шляху довжиною до 32767 символів.

У Windows 10 (1607) поведінка функцій для роботи з файлами змінилося: з'явилася можливість відключити перевірку обмежень MAX_PATH на рівні системи.

Це стосується наступних функцій:Для роботи з каталогами: CreateDirectoryW, CreateDirectoryExW, GetCurrentDirectoryW, RemoveDirectoryW, SetCurrentDirectoryW. для роботи з файлами: CopyFileW, CopyFile2, CopyFileExW, CreateFileW, CreateFile2, CreateHardLinkW, CreateSymbolicLinkW, DeleteFileW, FindFirstFileW, FindFirstFileExW, FindNextFileW, GetFileAttributesW, GetFileAttributesExW, SetFileAttributesW, GetFullPathNameW, GetLongPathNameW, MoveFileW, MoveFileExW, MoveFileWithProgressW, ReplaceFileW, SearchPathW, FindFirstFileNameW, FindNextFileNameW, FindFirstStreamW, FindNextStreamW, GetCompressedFileSizeW, GetFinalPathNameByHandleW.

Це позбавляє від необхідності використовувати префікс \\?\ і потенційно дає шанс додатками, що працюють безпосередньо або опосередковано через Win API, отримати підтримку довгих шляхів без необхідності їх перезбирання. Як активувати цю можливість описано в кінці статті.

.Net Framework

Хоча .Net Framework і використовує Win API для роботи з файлами — попередній зміна не принесло б результату, т. к. в код BCL вбудовані попередні перевірки на допустимість довжини імен каталогів і файлів, і до виклику функції Win API справа навіть не доходило, видаючи відоме виключення. На численні прохання співтовариства (понад 4500 на UserVoice) у версії 4.6.2 з коду BCL вирізали перевірки обмеження довжини шляху, віддаючи це на відкуп операційної та файлової систем!

Ось що це дає:
  • При використанні префікса "\\?\" ми можемо працювати з довгими шляхами, як у Win API,
    Directory.CreateDirectory("\\\\?\\" + long_dir_name);
  • Якщо активувати нативну підтримку довгих імен файлів Windows 10 (1607), то навіть не потрібно використовувати префікс!
Як включити:
  • Використовувати .Net Framework 4.6.2 як мета при складанні програми.
  • Використовувати конфігураційний файл, наприклад, якщо програма вже було зібрано під .Net 4.0:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup> 
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>
</startup>
<runtime>
<AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" />
</runtime>
</configuration>


.Net Core

Тут підтримку довгих шляхів анонсували ще в листопаді 2015 року. Мабуть позначилося Open Source природа проекту і відсутність суворої необхідності забезпечення зворотної сумісності.

Як включити:
Все працює з коробки. На відміну від реалізації .Net Framework – тут немає необхідності в префіксу "\\?\" – він додається автоматично при необхідності.

Ось тут можна подивитися приклад.

Як включити підтримку довгих шляхів у Windows 10 (1607)

Ця можливість відключена за замовчуванням. Це пояснюється тим, що дана функція є експериментальною, і є необхідність допрацьовувати різні підсистеми і програми для повної підтримки.

Включити вбудовану підтримку довгих шляхів можна створивши або змінивши параметр реєстру: HKLM\SYSTEM\CurrentControlSet\Control\FileSystem Параметр LongPathsEnabled (Тип: REG_DWORD) 1 – відповідає значенню включено.



Або через групові політики (Win+R\gpedit.msc) Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths.</i Воно ж в локалізованому варіанті: Налаштування комп'ютера > Адміністративні шаблони > Система > Файлова система > Включити довгі шляхи Win32.



Далі джерела розходяться в думці щодо маніфесту (або я неправильно зрозумів, але на даний момент перевірити не маю можливості). Наприклад, в документації MSDN написано, що маніфест можна використовувати в якості альтернативного способу активації підтримки довгих шляхів в окремих додатках, а в блозі MSDN зазначено, що це є другим обов'язковим кроком після активації в політиках.
Але вони сходяться в форматі завдання даної опції:

<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings xmlns:ws2="http://schemas.microsoft.com/SMI/2016/WindowsSettings">
<ws2:longPathAware>true</ws2:longPathAware>
</windowsSettings>
</application>

З CMD, на жаль, це не спрацює, на даний момент, з-за особливостей роботи з шляхами, а в PowerShell має всі заробити.

p.s.

На цьому мій невеликий п'ятничний піст закінчується, залишивши за рамками питання повноти реалізації підтримки довгих шляхів у Windows 10 (1607), або працездатність при використанні різних комбінацій редакцій Windows файлових систем і API. По мірі надходження нових фактів і результатів експериментів пост буде оновлюватися.

Спасибі за увагу!
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.