Максимальна довжина рядка командного рядка


110

У Windows яка максимальна довжина рядка командного рядка? Значення, якщо я вказую програму, яка бере аргументи в командному рядку, наприкладabc.exe -name=abc

Простий додаток консолі, який я написав, приймає параметри через командний рядок, і я хочу знати, яка максимально допустима сума.


Якщо когось цікавить, я працював над тим, щоб програми підтримували довші командні рядки . Якщо припустити, що ми можемо створити достатню підтримку для цього, це призведе до повного усунення обмежень, не вимагаючи від Microsoft нічого виправити, і таким чином легко сумісний. Не дуже відповідь на питання, але варто мати посилання тут ІМО.
аластер

Відповіді:


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 #), і здається, що рядок "аргументи" для команди командного рядка обмежений 2048 символами в XP та 32768 символами в Win7. Я не впевнений, на що відноситься межа 8191, але я не знайшов жодних доказів цього.


Звідки ти взяв цифру 32k для Win7? Я не можу знайти джерело для цього. Ви думаєте про розмір блоку навколишнього середовища ?
Попс

1
Можливо. Я знайшов фігуру 32k, передавши довші та довші аргументи до процесу через клас C # ProcessStartInfo. Він викидає виняток після 32k.
Sugrue

10
@LordTorgamus, Ліміт 32k обумовлений структурою UNICODE_STRING (довжина ушорту). Згідно зі статтею Реймонда Чена щодо теми CMD обмежує рядки до 8192 символів (я вважаю, що повернення вантажу є остаточним символом), а ShellExecuteEx обмежує "INTERNET_MAX_URL_LENGTH (близько 2048 р.)"
NtscCobalt

1
А як щодо PowerShell в Windows 10?
Nilzor

1
8191 для cmd і подібних даних здається дуже реальним, просто наткнувся на це, коли виконував дуже довгу команду через Exec в MSBuild
stijn

41

Як @Sugrue, я також викопував стару нитку.

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

Незалежно від того, як ви запускаєте програму з аргументами командного рядка, вона переходить до 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(бо WCHAR2 байти завдовжки).

Є кілька кроків, щоб розібратися в цій кількості, але, сподіваюся, це зрозуміло.


Крім того, щоб підтримати @sunetos відповісти, що прийнято. 8191 - максимальна кількість, яку можна ввестиcmd.exe , якщо ви перевищуєте цю межу, The input line is too long.створюється помилка. Отже, відповідь правильна, незважаючи на те, що cmd.exeце не єдиний спосіб передавати аргументи для нового процесу.


Довжина становить до 32 766 символів, оскільки зберігається рядок з нульовим завершенням.
Ерік Нд

1
Процеси не називаються в просторі імен об'єктів, тому використовується ObjectAttributesлише для дескриптора безпеки і робить повертається ручку спадковою. Командний рядок передається у поле ProcessParameters, на яке посилається Блок середовища середовища (PEB). Зі старими NtCreateProcessці параметри потрібно записати в дочірній процес через NtWriteVirtualMemory. В даний час NtCreateUserProcessвикористовується, який поєднує в собі кілька дзвінків в єдину службу ядра - наприклад , створення Section, Processі Threadоб'єкти; і запис параметрів процесу.
Ерик Нд

@eryksun Структура UNICODE_STRING не обов'язково зберігає нульовий термінатор.
賈 可 Джекі

@ 賈 可 Джекі, очевидно, що підрахунок рядка не обов'язково використовує рядок з нульовим завершенням. Наприклад, за допомогою функцій реєстру NTAPI ми можемо створювати та отримувати доступ до імен ключів із наявними в них нулями, але вони не будуть доступні за допомогою функцій реєстру WINAPI, які використовують нульові завершені рядки. Так само WINAPI CreateProcessWвикористовує рядок з нульовим завершенням для командного рядка та шляху програми. Ліміт - 32 767 - 1, тобто 32 766 символів.
Ерік

@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.
аластер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.