Longueur maximale de la chaîne de ligne de commande

110

Sous Windows, quelle est la longueur maximale d'une chaîne de ligne de commande? Cela signifie que si je spécifie un programme qui prend des arguments sur la ligne de commande tels queabc.exe -name=abc

Une simple application console que j'ai écrite prend des paramètres via la ligne de commande et je veux savoir quel est le montant maximum autorisé.

ST3
la source
Si quelqu'un est intéressé, j'ai travaillé sur un moyen pour que les programmes prennent en charge des lignes de commande plus longues . En supposant que nous puissions créer suffisamment de support pour cela, cela supprimerait complètement les restrictions sans exiger de Microsoft de réparer quoi que ce soit, et d'une manière qui soit tout à fait compatible. Pas vraiment une réponse à la question, mais cela vaut la peine d'avoir un lien ici IMO.
alastair

Réponses:

87

À partir de la documentation Microsoft: Limitation de la chaîne de ligne de commande de l'invite de commande (Cmd. Exe)

Sur les ordinateurs exécutant Microsoft Windows XP ou version ultérieure, la longueur maximale de la chaîne que vous pouvez utiliser à l'invite de commandes est de 8 191 caractères.

sunetos
la source
33
Cela ne s'applique qu'aux programmes exécutés via l'invite de commande (selon la question). Les raccourcis (.lnk) sont limités à 260 caractères, CreateProcess à 32767 et ShellExecute à environ 2048. Selon l'article de Raymond Chen sur le sujet
NtscCobalt
2 ^ 13-1 caractères, cela implique que quelque chose est suivi dans un nombre de 16 et cela utilise 13 de ces bits. Je me demande à quoi servent les 3 autres bits?
Sqeaky
@ulrichb Et maintenant, ce lien est également rompu après une autre migration de blog. L'article cité peut maintenant être trouvé sur devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
Adam Rosenfield
72

Désolé d'avoir creusé un vieux fil, mais je pense que la réponse de sunetos n'est pas correcte (ou n'est pas la réponse complète). J'ai fait quelques expériences (en utilisant ProcessStartInfo en c #) et il semble que la chaîne «arguments» pour une commande en ligne de commande soit limitée à 2048 caractères sous XP et 32768 caractères sous Win7. Je ne sais pas à quoi fait référence la limite de 8191, mais je n'en ai encore trouvé aucune preuve.

Sugrue
la source
Où avez-vous obtenu le chiffre de 32k pour Win7? Je ne trouve pas de source pour ça. Pensez-vous à la taille du bloc d'environnement ?
Pops
1
Peut-être. J'ai trouvé le chiffre 32k en passant des arguments de plus en plus longs à un processus via la classe C # ProcessStartInfo. Il lève une exception après 32k.
Sugrue
10
@LordTorgamus, 32k La limite est due à la UNICODE_STRING structure (longueur de ushort). Selon l'article de Raymond Chen sur le sujet, CMD limite les lignes à 8192 caractères (je suppose que le retour de carrage est le caractère final) et ShellExecuteEx limite à "INTERNET_MAX_URL_LENGTH (environ 2048)"
NtscCobalt
1
Qu'en est-il sous PowerShell sur Windows 10?
Nilzor
1
8191 pour cmd et les likes semblent très réels, je viens de rencontrer cela lors de l'exécution d'une très longue commande via Exec dans MSBuild
stijn
41

En tant que @Sugrue, je suis également en train de creuser un vieux fil.

Pour expliquer pourquoi il y a 32768 (je pense que cela devrait être 32767, mais croyons le résultat des tests expérimentaux), nous devons creuser dans l'API Windows.

Peu importe la façon dont vous lancez le programme avec des arguments de ligne de commande, il va à ShellExecute , CreateProcess ou à toute autre version étendue. Ces API englobent essentiellement d'autres API de niveau NT qui ne sont pas officiellement documentées. Autant que je sache, ces appels enveloppent NtCreateProcess , qui nécessite la structure OBJECT_ATTRIBUTES en tant que paramètre, pour créer cette structure, InitializeObjectAttributes est utilisé. Dans cet endroit, nous voyons UNICODE_STRING. Alors maintenant, jetons un œil à cette structure:

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

Il utilise la USHORTvariable (longueur 16 bits [0; 65535]) pour stocker la longueur. Et selon cela , la longueur indique la taille en octets, pas en caractères. Nous avons donc: 65535 / 2 = 32767(car il WCHARfait 2 octets de long).

Il y a quelques étapes pour creuser ce nombre, mais j'espère que c'est clair.


Aussi, pour soutenir @sunetos, répondez à ce qui est accepté. 8191 est un nombre maximum autorisé à entrer cmd.exe, si vous dépassez cette limite, une The input line is too long.erreur est générée. Donc, la réponse est correcte malgré le fait que ce cmd.exen'est pas la seule façon de passer des arguments pour un nouveau processus.

ST3
la source
La longueur peut aller jusqu'à 32 766 caractères car une chaîne terminée par un caractère nul est stockée.
Eryk Sun
1
Les processus ne sont pas nommés dans l'espace de noms de l'objet, donc le ObjectAttributesn'est utilisé que pour le descripteur de sécurité et rend le handle retourné héritable. La ligne de commande est passée dans le ProcessParameters, qui est référencé par le Process Environment Block (PEB). Avec l'ancien NtCreateProcess, ces paramètres doivent être écrits dans le processus fils via NtWriteVirtualMemory. De nos jours , NtCreateUserProcessest utilisé, qui combine plusieurs appels à un service unique noyau - par exemple création Section, Processet des Threadobjets; et écrire les paramètres du processus.
Eryk Sun
@eryksun La structure UNICODE_STRING ne stocke pas nécessairement le terminateur nul.
賈 可 Jacky
@ 賈 可 Jacky, évidemment une chaîne comptée n'utilise pas nécessairement une chaîne terminée par un nul. Par exemple, avec les fonctions de registre NTAPI, nous pouvons créer et accéder à des noms de clés contenant des valeurs nulles, mais ils ne seront pas accessibles avec les fonctions de registre WINAPI, qui utilisent des chaînes terminées par un null. De même, WINAPI CreateProcessWutilise une chaîne terminée par un nul pour la ligne de commande et le chemin de l'application. La limite est de 32 767 - 1, soit 32 766 caractères.
Eryk Sun
@eryksun J'ai trouvé que le document sur les limites de taille des éléments de registre sur MSDN indiquait que la longueur maximale d'un nom de clé de registre est de 255 caractères, mais en fait, vous pouvez créer un nom de clé de 256 caractères. Étant donné que la chaîne de style C n'est qu'un pointeur sans limite de longueur, donc je suppose qu'il peut être possible de passer une chaîne de 32767 caractères à la fonction unicode CreateProcessW, elle peut stocker la longueur exacte dans la UNICODE_STRINGstructure et définir à la fois Lengthet MaximumLengthà 65534 , c'est un argument juridique pour NtCreateProcess.
賈 可 Jacky
3

Dans Windows 10, il reste 8191 caractères ... du moins sur ma machine.

Il coupe simplement tout texte après 8191 caractères. Eh bien, en fait, j'ai 8196 caractères, et après 8196, alors ça ne me laisse plus taper.

Voici un script qui testera la durée d'une instruction que vous pouvez utiliser. Eh bien, en supposant que vous ayez installé 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
la source
C'est la limite pour cmd.exe. Comme l'indique la réponse ci-dessus, la limite réelle est de 32 768 caractères en raison de UNICODE_STRING.
alastair le