Maximale Länge der Befehlszeilenzeichenfolge

108

Wie lang ist eine Befehlszeilenzeichenfolge in Windows maximal? Das heißt, wenn ich ein Programm spezifiziere, das Argumente in der Befehlszeile akzeptiert, wie zabc.exe -name=abc

Eine einfache Konsolenanwendung, die ich geschrieben habe, nimmt Parameter über die Befehlszeile entgegen und möchte wissen, wie viel maximal zulässig ist.

ST3
quelle
Wenn jemand interessiert ist, habe ich an einer Möglichkeit gearbeitet, dass Programme längere Befehlszeilen unterstützen . Vorausgesetzt, wir können genügend Unterstützung dafür aufbauen, würden die Einschränkungen vollständig aufgehoben, ohne dass Microsoft irgendetwas reparieren muss, und zwar auf eine Weise, die unkompliziert kompatibel ist. Keine wirkliche Antwort auf die Frage, aber es lohnt sich, hier einen Link zu haben, IMO.
Alastair

Antworten:

85

Aus der Microsoft-Dokumentation: Einschränkung der Befehlszeilenzeichenfolge für die Eingabeaufforderung (Cmd. Exe)

Auf Computern mit Microsoft Windows XP oder höher beträgt die maximale Länge der Zeichenfolge, die Sie an der Eingabeaufforderung verwenden können, 8191 Zeichen.

Sunetos
quelle
32
Dies gilt nur für die Programme, die tatsächlich über die Eingabeaufforderung ausgeführt werden (gemäß der Frage). Verknüpfungen (.lnk) sind auf 260 Zeichen, CreateProcess auf 32767 und ShellExecute auf ca. 2048 begrenzt. Laut Raymond Chens Artikel zu diesem Thema
NtscCobalt
2 ^ 13-1 Zeichen, was bedeutet, dass etwas in einer 16-Zahl verfolgt wird, und dies verwendet 13 dieser Bits. Ich frage mich, wozu die anderen 3 Bits dienen.
Sqeaky
@ulrichb Und jetzt ist dieser Link auch nach einer weiteren Blog-Migration unterbrochen. Der zitierte Artikel kann jetzt unter devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
Adam Rosenfield
71

Es tut mir leid , dass ich einen alten Thread ausgegraben habe , aber ich denke , die Antwort von sunetos ist nicht korrekt (oder nicht die vollständige Antwort). Ich habe einige Experimente durchgeführt (mit ProcessStartInfo in c #) und es scheint, dass die Zeichenfolge 'Argumente' für einen Befehlszeilenbefehl in XP auf 2048 Zeichen und in Win7 auf 32768 Zeichen beschränkt ist. Ich bin mir nicht sicher, worauf sich das 8191-Limit bezieht, aber ich habe noch keine Beweise dafür gefunden.

Sugrue
quelle
Woher hast du die 32k-Zahl für Win7? Ich kann keine Quelle dafür finden. Denken Sie an die Größe des Umgebungsblocks ?
Pops
1
Möglicherweise. Ich fand die 32k-Zahl, indem ich immer längere Argumente über die C # ProcessStartInfo-Klasse an einen Prozess übergab. Nach 32k wird eine Ausnahme ausgelöst.
Sugrue
10
@ LordTorgamus, Das 32k-Limit ist auf die UNICODE_STRING- Struktur (kurze Länge) zurückzuführen. Laut Raymond Chens Artikel zum Thema CMD werden Zeilen auf 8192 Zeichen begrenzt (ich würde annehmen, dass die Carrage Return das letzte Zeichen ist) und ShellExecuteEx auf "INTERNET_MAX_URL_LENGTH (um 2048)"
NtscCobalt
1
Was ist mit unter PowerShell unter Windows 10?
Nilzor
1
8191 für cmd und dergleichen scheint sehr real zu sein, bin gerade darauf gestoßen, als ein sehr langer Befehl über Exec in MSBuild ausgeführt wurde
stijn
40

Als @Sugrue grabe ich auch einen alten Thread aus.

Um zu erklären, warum es 32768 (ich denke, es sollte 32767 sein, aber lassen Sie uns das experimentelle Testergebnis glauben) gibt, müssen wir die Windows-API einschränken.

Unabhängig davon , wie Sie ein Programm mit Befehlszeilenargumenten starten, wird es an ShellExecute , CreateProcess oder eine erweiterte Version gesendet . Diese APIs umfassen im Wesentlichen andere NT-APIs, die nicht offiziell dokumentiert sind. Soweit ich weiß, wird in diesen Aufrufen NtCreateProcess umbrochen , für das die Struktur OBJECT_ATTRIBUTES als Parameter erforderlich ist. InitializeObjectAttributes wird verwendet. An diesem Ort sehen wir UNICODE_STRING. Schauen wir uns nun diese Struktur an:

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

Es verwendet USHORT(16-Bit - Länge [0; 65535]) Variablen zu speichern Länge. Und nach dieser zeigt Länge Größe in Bytes, nicht Zeichen. Wir haben also: 65535 / 2 = 32767(weil WCHARes 2 Bytes lang ist).

Es gibt ein paar Schritte, um diese Zahl zu untersuchen, aber ich hoffe, es ist klar.


Um @sunetos zu unterstützen, antworten Sie auch, was akzeptiert wird. 8191 ist eine maximale Anzahl, die eingegeben werden cmd.exedarf. Wenn Sie diesen Grenzwert überschreiten, wird ein The input line is too long.Fehler generiert. Die Antwort ist also richtig, obwohl dies cmd.exenicht die einzige Möglichkeit ist, Argumente für einen neuen Prozess zu übergeben.

ST3
quelle
Die Länge beträgt bis zu 32.766 Zeichen, da eine nullterminierte Zeichenfolge gespeichert ist.
Eryk Sun
1
Prozesse werden im Objektnamespace nicht benannt, daher ObjectAttributeswird der nur für den Sicherheitsdeskriptor verwendet und macht das zurückgegebene Handle vererbbar. Die Befehlszeile wird in übergeben ProcessParameters, auf die der Process Environment Block (PEB) verweist. Beim alten NtCreateProcessmüssen diese Parameter über in den untergeordneten Prozess geschrieben werden NtWriteVirtualMemory. Heutzutage NtCreateUserProcessverwendet, die mehrere Anrufe zu einem einzigen Kernel Service verbindet - zB Erstellen Section, Processund ThreadObjekte; und Schreiben der Prozessparameter.
Eryk Sun
@eryksun Die Struktur UNICODE_STRING speichert nicht unbedingt den Nullterminator.
y 可 Jacky
@ 賈 可 Jacky, offensichtlich verwendet eine gezählte Zeichenfolge nicht unbedingt eine nullterminierte Zeichenfolge. Mit den NTAPI-Registrierungsfunktionen können wir beispielsweise Schlüsselnamen mit Nullen erstellen und darauf zugreifen, aber mit WINAPI-Registrierungsfunktionen, die nullterminierte Zeichenfolgen verwenden, können sie nicht aufgerufen werden. Ebenso CreateProcessWverwendet WINAPI eine nullterminierte Zeichenfolge für die Befehlszeile und den Anwendungspfad. Das Limit beträgt 32.767 - 1, dh 32.766 Zeichen.
Eryk Sun
@eryksun Ich fand heraus, dass das Dokument über Größenbeschränkungen für Registrierungselemente in MSDN besagt, dass die maximale Länge eines Registrierungsschlüsselnamens 255 Zeichen beträgt, aber tatsächlich können Sie einen Schlüsselnamen mit 256 Zeichen erstellen. Da die Zeichenfolge im C-Stil nur ein Zeiger ohne Längenbeschränkung ist und es daher möglich ist, eine Zeichenfolge mit 32.767 Zeichen an die Unicode-Funktion zu übergeben CreateProcessW, kann sie die genaue Länge in der UNICODE_STRINGStruktur speichern und beide Lengthund MaximumLengthauf 65.534 setzen ist es ein rechtliches Argument für NtCreateProcess.
y 可 Jacky
2

In Windows 10 sind es immer noch 8191 Zeichen ... zumindest auf meinem Computer.

Nach 8191 Zeichen wird nur Text abgeschnitten. Eigentlich habe ich 8196 Zeichen und nach 8196 kann ich einfach nicht mehr tippen.

Hier ist ein Skript, mit dem getestet wird, wie lange eine Anweisung verwendet werden kann. Angenommen, Sie haben gawk / awk installiert.

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
quelle
Das ist die Grenze für cmd.exe. Wie in der obigen Antwort angegeben, beträgt das tatsächliche Limit aufgrund von UNICODE_STRING 32.768 Zeichen.
Alastair