Maksymalna długość ciągu wiersza poleceń

110

Jaka jest maksymalna długość ciągu wiersza poleceń w systemie Windows? Oznacza to, że jeśli określę program, który przyjmuje argumenty w wierszu poleceń, takie jakabc.exe -name=abc

Prosta aplikacja konsolowa, którą napisałem, pobiera parametry z wiersza poleceń i chcę wiedzieć, jaka jest maksymalna dopuszczalna kwota.

ST3
źródło
Jeśli ktoś jest zainteresowany, pracowałem nad sposobem, aby programy obsługiwały dłuższe wiersze poleceń . Zakładając, że uda nam się zbudować dla niego wystarczające wsparcie, całkowicie usunie to ograniczenia bez konieczności naprawiania czegokolwiek przez Microsoft iw sposób, który jest bezpośrednio zgodny. Niezupełnie odpowiedź na pytanie, ale warto mieć tutaj link IMO.
alastair

Odpowiedzi:

87

Z dokumentacji firmy Microsoft: Ograniczenie ciągu wiersza polecenia w wierszu polecenia (Cmd. Exe)

Na komputerach z systemem Microsoft Windows XP lub nowszym maksymalna długość ciągu, którego można użyć w wierszu polecenia, to 8191 znaków.

sunetos
źródło
33
Dotyczy to tylko programów faktycznie uruchamianych z wiersza polecenia (zgodnie z pytaniem). Skróty (.lnk) są ograniczone do 260 znaków, CreateProcess do 32767, a ShellExecute do około 2048. Zgodnie z artykułem Raymonda Chena na ten temat
NtscCobalt
2 ^ 13-1 znaków, co oznacza, że ​​coś jest śledzone w 16 liczbach, a to wykorzystuje 13 z tych bitów. Zastanawiam się, do czego służą pozostałe 3 bity?
Sqeaky
@ulrichb A teraz ten link również jest zepsuty po kolejnej migracji bloga. Cytowany artykuł można teraz znaleźć na devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
Adam Rosenfield
72

Przepraszam, że odkopałem stary wątek, ale myślę, że odpowiedź Sunetos nie jest poprawna (lub nie jest pełną odpowiedzią). Zrobiłem kilka eksperymentów (używając ProcessStartInfo w c #) i wydaje się, że ciąg „argumentów” dla polecenia wiersza poleceń jest ograniczony do 2048 znaków w XP i 32768 znaków w Win7. Nie jestem pewien, do czego odnosi się limit 8191, ale nie znalazłem jeszcze żadnych dowodów na to.

Sugrue
źródło
Skąd masz liczbę 32k dla Win7? Nie mogę znaleźć dla tego źródła. Czy myślisz o wielkości bloku środowiska ?
Pojawia się
1
Możliwie. Znalazłem liczbę 32k, przekazując coraz dłuższe argumenty do procesu za pośrednictwem klasy C # ProcessStartInfo. Zgłasza wyjątek po 32k.
Sugrue
10
@LordTorgamus, limit 32k to spowodowane UNICODE_STRING struktury (długość ushort). Zgodnie z artykułem Raymonda Chena na ten temat, CMD ogranicza linie do 8192 znaków (zakładałbym, że powrót carrage jest ostatnim znakiem), a ShellExecuteEx ogranicza do „INTERNET_MAX_URL_LENGTH (około 2048 r.)”
NtscCobalt
1
A co z PowerShell w Windows 10?
Nilzor,
1
8191 dla cmd i polubienia wydają się bardzo realne, po prostu napotkałem to podczas wykonywania bardzo długiego polecenia przez Exec w MSBuild
stijn
41

Jako @Sugrue również wykopuję stary wątek.

Aby wyjaśnić, dlaczego istnieje 32768 (myślę, że powinno być 32767, ale uwierzmy w wynik testów eksperymentalnych) ograniczenie znaków, musimy zagłębić się w Windows API.

Bez względu na to, jak uruchomisz program z argumentami wiersza poleceń, trafi on do ShellExecute , CreateProcess lub dowolnej rozszerzonej ich wersji. Te interfejsy API zasadniczo opakowują inne API poziomu NT, które nie są oficjalnie udokumentowane. O ile wiem, te wywołania zawijają NtCreateProcess , który wymaga struktury OBJECT_ATTRIBUTES jako parametru, do utworzenia tej struktury jest używany InitializeObjectAttributes . W tym miejscu widzimy UNICODE_STRING. Przyjrzyjmy się teraz tej strukturze:

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

Używa USHORTzmiennej (długość 16-bitowa [0; 65535]) do przechowywania długości. I zgodnie z tym długość wskazuje rozmiar w bajtach, a nie w znakach. Mamy więc: 65535 / 2 = 32767(ponieważ WCHARma 2 bajty).

Jest kilka kroków, aby zagłębić się w ten numer, ale mam nadzieję, że jest jasny.


Ponadto, aby wspierać @sunetos, odpowiedz, co jest akceptowane. 8191 to maksymalna dozwolona liczba cmd.exe, jeśli przekroczysz ten limit, The input line is too long.zostanie wygenerowany błąd. Tak więc odpowiedź jest prawidłowa, mimo że cmd.exenie jest to jedyny sposób przekazywania argumentów za nowym procesem.

ST3
źródło
Długość wynosi do 32766 znaków, ponieważ przechowywany jest ciąg zakończony znakiem null.
Eryk Sun
1
Procesy nie są nazywane w przestrzeni nazw obiektu, więc ObjectAttributesjest używany tylko jako deskryptor zabezpieczeń i sprawia, że ​​zwracany uchwyt jest dziedziczony. Wiersz poleceń jest przekazywany w ProcessParameters, do którego odwołuje się blok środowiska procesu (PEB). W przypadku starej wersji NtCreateProcessparametry te muszą zostać zapisane w procesie potomnym za pośrednictwem NtWriteVirtualMemory. Obecnie NtCreateUserProcessjest używany, który łączy w sobie kilka połączeń do pojedynczej usługi jądra - np Tworzenie Section, Processoraz Threadobiektów; i zapisywanie parametrów procesu.
Eryk Sun
@eryksun Struktura UNICODE_STRING niekoniecznie przechowuje terminator zerowy.
賈 可 Jacky
@ 賈 可 Jacky, oczywiście policzony ciąg niekoniecznie musi zawierać ciąg zakończony znakiem null. Na przykład, dzięki funkcjom rejestru NTAPI możemy tworzyć i uzyskiwać dostęp do nazw kluczy zawierających wartości null, ale nie będą one dostępne za pomocą funkcji rejestru WINAPI, które używają ciągów zakończonych znakiem null. Podobnie WINAPI CreateProcessWużywa łańcucha zakończonego znakiem null w wierszu poleceń i ścieżce aplikacji. Limit wynosi 32 767 - 1, czyli 32 766 znaków.
Eryk Sun
@eryksun Dowiedziałem się, że w dokumencie dotyczącym limitów rozmiaru elementów rejestru w witrynie MSDN podano, że maksymalna długość nazwy klucza rejestru to 255 znaków, ale w rzeczywistości można utworzyć nazwę klucza składającą się z 256 znaków. Ponieważ ciąg C-styl jest po prostu wskaźnik bez limitu długości, więc myślę, że może to być możliwe, aby przekazać ciąg 32,767 znaków do funkcji unicode CreateProcessWmoże przechowywać dokładną długość w UNICODE_STRINGstrukturze i ustawić zarówno Lengthi MaximumLengthdo 65,534 , jest to argument prawny za NtCreateProcess.
賈 可 Jacky
3

W systemie Windows 10 wciąż jest 8191 znaków ... przynajmniej na moim komputerze.

Po prostu odcina dowolny tekst po 8191 znakach. Cóż, właściwie mam 8196 znaków, a po 8196 po prostu nie pozwoli mi już pisać.

Oto skrypt, który sprawdzi, jak długo możesz użyć instrukcji. Zakładając, że masz zainstalowany 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
Joseph Dewey
źródło
To jest limit dla cmd.exe. Jak wskazuje powyższa odpowiedź, rzeczywisty limit to 32768 znaków z powodu UNICODE_STRING.
alastair