Максимальная длина строки командной строки

110

Какова максимальная длина строки командной строки в Windows? Это означает, что я укажу программу, которая принимает аргументы в командной строке, напримерabc.exe -name=abc

Написанное мною простое консольное приложение принимает параметры через командную строку, и я хочу знать, какова максимально допустимая сумма.

ST3
источник
Если кому-то интересно, я работал над тем, чтобы программы поддерживали более длинные командные строки . Предполагая, что мы сможем создать для него достаточную поддержку, это полностью снимет ограничения, не требуя от Microsoft исправления чего-либо, и таким образом, чтобы это было напрямую совместимо. Не совсем ответ на вопрос, но стоит иметь ссылку здесь, IMO.
Аластер

Ответы:

87

Из документации Microsoft: Командная строка (Cmd. Exe) ограничение строки командной строки

На компьютерах под управлением Microsoft Windows XP или более поздней версии максимальная длина строки, которую можно использовать в командной строке, составляет 8191 символ.

сунетос
источник
33
Это относится только к программам, фактически запускаемым через командную строку (согласно вопросу). Ярлыки (.lnk) ограничены 260 символами, CreateProcess - 32767, а ShellExecute - примерно 2048. Согласно статье Раймонда Чена на эту тему
NtscCobalt
2 ^ 13-1 символов, что означает, что что-то отслеживается в 16-м числе, и для этого используются 13 из этих бит. Интересно, для чего нужны остальные 3 бита?
Sqeaky
@ulrichb И теперь эта ссылка тоже не работает после очередного переноса блога. Цитируемую
Адам Розенфилд
72

Извините за то, что выкопал старую ветку , но я думаю, что ответ sunetos неверен (или не является полным ответом). Я провел несколько экспериментов (используя ProcessStartInfo в C #), и мне кажется, что строка «arguments» для команды командной строки ограничена 2048 символами в XP и 32768 символами в Win7. Я не уверен, что означает ограничение 8191, но я пока не нашел никаких доказательств этого.

Sugrue
источник
Где ты взял цифру 32к для Win7? Я не могу найти для этого источник. Вы думаете о размере блока окружения ?
Pops
1
Возможно. Я нашел цифру 32k, передавая все более длинные аргументы процессу через класс C # ProcessStartInfo. Выдает исключение после 32k.
Sugrue
10
@LordTorgamus, Предел 32к обусловлен структурой UNICODE_STRING (длина ushort). Согласно статье Рэймонда Чена на эту тему, CMD ограничивает строки до 8192 символов (я бы предположил, что возвращение каретки является последним символом), а ShellExecuteEx ограничивает «INTERNET_MAX_URL_LENGTH (около 2048)»
NtscCobalt
1
А что насчет PowerShell в Windows 10?
Nilzor
1
8191 для cmd и тому подобного кажется вполне реальным, просто столкнулся с этим при запуске очень длинной команды через Exec в MSBuild
stijn
41

Как @Sugrue я также выкапываю старую ветку.

Чтобы объяснить, почему существует ограничение на 32768 символов (я думаю, это должно быть 32767, но давайте поверить в результат экспериментального тестирования), нам нужно покопаться в Windows API.

Независимо от того, как вы запускаете программу с аргументами командной строки, она переходит в ShellExecute , CreateProcess или любую расширенную их версию. Эти API-интерфейсы в основном охватывают другие API уровня NT, которые официально не документированы. Насколько мне известно, эти вызовы охватывают NtCreateProcess , который требует в качестве параметра структуры OBJECT_ATTRIBUTES , для создания этой структуры используется InitializeObjectAttributes . В этом месте мы видим UNICODE_STRING. Итак, теперь давайте взглянем на эту структуру:

typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING;

Он использует USHORTпеременную (16-битная длина [0; 65535]) для хранения длины. И в соответствии с этим длина указывает размер в байтах, а не в символах. Итак, у нас есть: 65535 / 2 = 32767(потому что WCHARэто 2 байта).

Есть несколько шагов, чтобы разобраться в этом числе, но я надеюсь, что это понятно.


Также, чтобы поддержать @sunetos, ответьте, что принято. 8191 - это максимальное число, которое можно ввести cmd.exe, если вы превысите этот предел, The input line is too long.будет сгенерирована ошибка. Итак, ответ правильный, несмотря на то, что cmd.exeэто не единственный способ передать аргументы новому процессу.

ST3
источник
Длина до 32 766 символов, потому что сохраняется строка с завершающим нулем.
Eryk Sun
1
Процессы не именуются в пространстве имен объектов, поэтому используется ObjectAttributesтолько для дескриптора безопасности и делает возвращаемый дескриптор наследуемым. Командная строка передается в, на ProcessParametersкоторый ссылается блок среды процесса (PEB). В старой версии NtCreateProcessэти параметры должны быть записаны в дочерний процесс через NtWriteVirtualMemory. В настоящее время NtCreateUserProcessиспользуется, который сочетает в себе несколько звонков в единую службу ядра - например , создание Section, Processи Threadобъекты; и запись параметров процесса.
Eryk Sun
@eryksun Структура UNICODE_STRING не обязательно хранит нулевой терминатор.
賈 可 Джеки
@ 賈 可 Джеки, очевидно, что подсчитываемая строка не обязательно использует строку с нулевым символом в конце. Например, с помощью функций реестра NTAPI мы можем создавать и получать доступ к именам ключей с нулями в них, но они не будут доступны с функциями реестра WINAPI, которые используют строки с завершающим нулем. Точно так же WINAPI CreateProcessWиспользует строку с завершающим нулем для командной строки и пути приложения. Предел составляет 32 767 - 1, то есть 32 766 символов.
Eryk Sun 03
@eryksun Я обнаружил, что в документе об ограничениях размера элемента реестра в MSDN сказано, что максимальная длина имени ключа реестра составляет 255 символов, но на самом деле вы можете создать имя ключа из 256 символов. Поскольку строка в стиле C - это просто указатель без ограничения длины, поэтому я предполагаю, что можно передать строку из 32 767 символов в функцию Unicode CreateProcessW, она может сохранить точную длину в UNICODE_STRINGструктуре и установить для обоих Lengthи MaximumLength65 534 , это юридический аргумент в пользу NtCreateProcess.
賈 可 Джеки
3

В Windows 10 это все еще 8191 символ ... по крайней мере, на моей машине.

Он просто обрезает любой текст после 8191 символа. Ну, на самом деле у меня 8196 символов, а после 8196 он просто не позволяет мне больше печатать.

Вот сценарий, который проверит, как долго вы можете использовать инструкцию. Ну, если у вас установлен gawk / awk.

echo rem this is a test of how long of a line that a .cmd script can generate >testbat.bat
gawk 'BEGIN {printf "echo -----";for (i=10;i^<=100000;i +=10) printf "%%06d----",i;print;print "pause";}' >>testbat.bat
testbat.bat
Джозеф Дьюи
источник
Это предел для cmd.exe. Как сказано в ответе выше, фактическое ограничение составляет 32 768 символов из-за UNICODE_STRING.
Аластер