Многим пользователям ПК под управлением ОС 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 на уровне системы.
Это избавляет от необходимости использовать префикса \? и потенциально даёт шанс приложениям, работающим напрямую или косвенно через 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)
Эта возможность по умолчанию отключена. Это объясняется тем, что данная функция является экспериментальной, и имеется необходимость дорабатывать различные подсистемы и приложения для полной поддержки.
Включить встроенную поддержку длинных путей можно создав или изменив следующий параметр системного реестра: HKLMSYSTEMCurrentControlSetControlFileSystem Параметр LongPathsEnabled (Тип: REG_DWORD) 1 – соответствует значению включено.
Или через групповые политики (Win+Rgpedit.msc) Computer Configuration > Administrative Templates > System > Filesystem > Enable NTFS long paths.Оно же в локализованном варианте: Конфигурация компьютера > Административные шаблоны > Система > Файловая система > Включить длинные пути 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. По мере поступления новых фактов и результатов экспериментов пост будет обновляться.
Спасибо за внимание!
Автор: fedorro