Комментарии 14
Так о чем текст собственно? Почему все файлы не переименовали? А надо?
Текст? Филлер для ленты новостей в стиле "Чен говорит почему вода мокрая, огонь горячий, а 8.3 до сих пор держат для совместимости, отрезать которую в принципе можно, даже клиенты поймут, но как это сделать уже мало кто понимает, потому, что в самой системе до сих пор сидит код из 90х, который работает, а работает - не трожь", заботливо перенесённый из профильного фида для амеров (см. ссылку). Из серии "For Dummies".
@maybe_elf : даты поправь, "ещё в 2_009 году" в русском языке не пишут, пишут слитно: "ещё в 2009 году"
Вчера еще @Travis_Macrif тоже годы с пробелами писал. Какое-то поветрие у редакторов Хабра. Похоже на бездумное использование типографа. Нейросетью.
Почему все файлы не переименовали?
Вдумчивое чтение оригинала показало, что…

Чтобы разбавить глум чем-нибудь полезным, расскажу, к каким практикам выживания пришёл.
Я насчитал три вида нормализации путей (возможно, позже натолкнусь ещё на какие-нибудь): резолвинг переменных (
%APPDATA%), резолвинг относительных путей (..) и резолвинг8.3. Первые две статические (файл может не существовать), третья динамическая (файл должен существовать).Я использую все три вида когда это только возможно. Например, в одной статье я прочитал, что если кто-то создаст процесс, используя имя исполняемого файла в формате
8.3, в таком виде вы его и получите. Теперь я всегда всё нормализую.Чтобы не мучаться с префиксами длинноты, начиная с Windows 10 1607 можно использовать ключ
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled. Проблема с ним в том, что он глобален. Так проектируют эти замечательные люди, счастья им, здоровья и успехов в личной жизни. Не то беда, что надо вешать триггер на изменение этого значения (любой дурак может поменять его на ноль в середине выполнения вашего алгоритма, и оно применится мгновенно, согласно прочитанному мною в другой статье), а то, что можно нечаянно сломать чужую совместимость.64К
хватит всемэто новыйMAX_PATH. Работать с ними неудобно. Одно время я пробовал завести пул статических буферов (из экономии), но быстро в нём запутался и теперь тупо аллоцирую 64К перед каждым вызовом.
Исправляйте, дополняйте, делитесь советами, дорогие коллеги.
Проблема с ним в том, что он глобален.
Насколько я помню, это не проблема, т.к. сам по себе этот ключ не заставит все приложения использовать длинные пути. Чтобы приложение их использовало, оно должно поддержку этой фичи задекларировать в своём манифесте. Поэтому включение длинных путей затронет лишь приложения, которые к этому готовы (а иначе зачем их разработчики сознательно задекларировали эту готовность?)
Пишу по памяти, мог ошибиться.
а иначе зачем их разработчики сознательно задекларировали эту готовность?
Насколько понимаю я, <ws2:longPathAware>true</ws2:longPathAware> в манифесте игнорируется, если в реестре у LongPathsEnabled стоит 0. Что, если какой-нибудь скрипт задействует утилиту, её манифест не срабатывает, она не может обработать длиннопуть, и на это завязан юз-кейс? А мы без спросу починим. Утилита отработает штатно, а скрипт этого не ожидает и упадёт. На самом деле, если бы я считал это вероятным, я бы и дальше мучился с префиксами, а так, прикинув, я решил, что упрощение кода за счёт избавления от префиксов стоит риска. Однако, для меня любое вмешательство в работу других приложений — проблема сама по себе.
Опять же, непонятно, что делать, если другая программа или лично юзер изменит значение во время работы моего приложения. Войну правок устраивать? Я пока поставил заглушку с сообщением, что программа больше не гарантирует правильную работу с файлами, а как дойдёт до продакшына, там поглядим, что с этим делать и сколько таких случаев будет. Надеюсь, что ноль.
Утилита отработает штатно, а скрипт этого не ожидает и упадёт.
Следует починить скрипт и автору скрипта сообщить, что он упорол косяк.
Опять же, непонятно, что делать, если другая программа или лично юзер изменит значение во время работы моего приложения.
Поскольку изменение применяется лишь после перезагрузки, то вашему приложению достаточно при своём старте проверить, будут ему доступны длинные пути или нет, а дальше можете спокойно работать, не опасаясь, что поведение поменяется на лету (не поменяется до рестарта, а рестарт ваше приложение не переживёт). Возвращать или нет - на ваше усмотрение. Например, мегапопулярный qBittorent возвращает при установке своего обновления (у него это в инсталляторе в виде включённой по умолчанию опции), что свидетельствует о том, что его разработчики длинные пути используют, но как-то умеют жить и с тем, что поддержка оных может оказаться и отключённой.
Поскольку изменение применяется лишь после перезагрузки
Это была ошибка с моей стороны. Спасибо, что ткнули пальцем. Действительно, в MSDN говорится:
The registry value will be cached by the system (per process) after the first call to an affected Win32 file or directory function (see below for the list of functions). The registry value will not be reloaded during the lifetime of the process.
Где-то я прочитал, что изменение вступает в силу немедленно, и не перепроверил. Теперь можно будет заглушку выкинуть перенести в инициализацию процесса.
скрипт этого не ожидает и упадёт.
Представим, что никакого системного переключателя длинных путей, который вам столь не нравится, вообще не существует.
А что если атакующий возьмёт да подменит вызываемую вами coolprogram.exe, своей одноимённой самописной программой, которая вне зависимости от системных настроек намеренно шарашит вам в ответ 100500 символов, чтобы вызвать переполнение буфера?
Если вы падаете от невалидных входных данных, это ваша вина. Либо предусмотрите, что вам могут прислать на вход нежданчик, либо удостоверьтесь, что данные получаете из доверенного источника (а если вы удостоверились, что coolprogram.exe это реально легитимная coolprogram.exe, то вы уж явно знаете может ли она прислать длинный путь в принципе и было ли это включено в ОС в момент вызова)
В настоящее время, пока MS ещё не внедрила так нравящуюся многим «виртуализацию», Windows представляет собой общежитие (и слава богу). По правилам общежития хорошая программа не должна (если только не в этом её цель) вмешиваться в работу других программ. Вообще никак. И оправдание «другие программы сами виноваты, что плохо написаны» не катит. (В старом Майкрософте это понимали, поэтому сделали у менеджера памяти режим SimCity). Иначе она получит заслуженную порку от юзеров. Чем больше юзеров, тем больше шансов, что у кого-то будет прострелена нога. Особенно когда юзеров миллионы.
При этом при всём я до сих пор считаю, что префиксы — бо́льшее зло. Из-за них я больше вреда могу нечаянно причинить юзерам. Что не мешает мне огорчаться наличием глобального рубильника, включенного в сеть последовательно с манифестами. Кто так проектирует? Манифеста недостаточно? И чтобы у каждого процесса API-функции вели себя в соответствии с этим манифестом независимо от всего? Я бы спроектировал именно так.
Я помню лет 8 назад надо было точно определить версию Windows, чтобы сделать развилку в коде, т.к. некоторые версии некорректно работали с каким-то замудрёным API, и нужен был воркараунд (от самого же Microsoft). И оказалось, что стандартные функции определения версии Windows отдавали неправильную версию “для обратной совместимости” после Windows 8 (что-то в этом роде). И в документации Microsoft был воркараунд типа “прочитайте версию ОС” в метаданных файла user32.dll, там точная версия. Т.е. настолько увязли в обратных совместимостях, что они теперь тупо создают проблемы, и решаются эти проблемы так, что Microsoft нужно поддерживать ещё больше барахла для обратной совместимости, иначе воркараунды обхода обратных совместимостей слетят (т.е. когда явно советуешь программно найти файл user32.dll, то уже точно не переименовать никогда).
на сколько помню, там не "не более одной точки", а всегда ровно одна точка, просто при пустом расширении её не рисовали. т.е. нельзя одновременно иметь файл "ABC" и "ABC." в одном каталоге
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
В Microsoft объяснили использование имён файлов в стиле MS‑DOS в Windows 11