Longitud máxima de la cadena de línea de comando

110

En Windows, ¿cuál es la longitud máxima de una cadena de línea de comando? Es decir, si especifico un programa que toma argumentos en la línea de comando comoabc.exe -name=abc

Una aplicación de consola simple que escribí toma parámetros a través de la línea de comando y quiero saber cuál es la cantidad máxima permitida.

ST3
fuente
Si alguien está interesado, he estado trabajando en una forma de que los programas admitan líneas de comando más largas . Suponiendo que podamos construir suficiente soporte para él, esto eliminaría las restricciones por completo sin requerir que Microsoft arregle nada, y de una manera que sea directamente compatible. No es realmente una respuesta a la pregunta, pero vale la pena tener un enlace aquí, en mi opinión.
alastair

Respuestas:

87

De la documentación de Microsoft: Límite de cadena de línea de comando del símbolo del sistema (Cmd. Exe)

En equipos que ejecutan Microsoft Windows XP o posterior, la longitud máxima de la cadena que puede usar en el símbolo del sistema es de 8191 caracteres.

sunetos
fuente
33
Esto solo se aplica a los programas que realmente se ejecutan a través del símbolo del sistema (según la pregunta). Los accesos directos (.lnk) están limitados a 260 caracteres, CreateProcess a 32767 y ShellExecute a aproximadamente 2048. Según el artículo de Raymond Chen sobre el tema
NtscCobalt
2 ^ 13-1 caracteres, eso implica que algo se rastrea en un número 16 y esto usa 13 de esos bits. Me pregunto para qué sirven los otros 3 bits.
Sqeaky
@ulrichb Y ahora ese enlace también está roto después de otra migración de blog. El artículo citado ahora se puede encontrar en devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
Adam Rosenfield
72

Lo siento por desenterrar un viejo hilo, pero creo que la respuesta de sunetos no es correcta (o no es la respuesta completa). Hice algunos experimentos (usando ProcessStartInfo en c #) y parece que la cadena de 'argumentos' para un comando de línea de comandos está limitada a 2048 caracteres en XP y 32768 caracteres en Win7. No estoy seguro de a qué se refiere el límite de 8191, pero aún no he encontrado ninguna evidencia de ello.

Sugrue
fuente
¿De dónde sacaste la cifra de 32k para Win7? No puedo encontrar una fuente para eso. ¿Estás pensando en el tamaño del bloque ambiental ?
Pops el
1
Posiblemente. Encontré la cifra de 32k pasando argumentos cada vez más largos a un proceso a través de la clase C # ProcessStartInfo. Lanza una excepción después de 32k.
Sugrue
10
@LordTorgamus, El límite de 32k se debe a la estructura UNICODE_STRING (longitud corta ). De acuerdo con el artículo de Raymond Chen sobre el tema, CMD limita las líneas a 8192 caracteres (supongo que la devolución de carrage es el carácter final) y ShellExecuteEx limita a "INTERNET_MAX_URL_LENGTH (alrededor de 2048)"
NtscCobalt
1
¿Qué pasa con PowerShell en Windows 10?
Nilzor
1
8191 para cmd y los me gusta parecen muy reales, simplemente me encontré con esto al ejecutar un comando muy largo a través de Exec en MSBuild
stijn
41

Como @Sugrue, también estoy desenterrando un viejo hilo.

Para explicar por qué hay 32768 (creo que debería ser 32767, pero creamos el resultado de las pruebas experimentales) limitación de caracteres, necesitamos profundizar en la API de Windows.

No importa cómo inicie el programa con argumentos de línea de comando, va a ShellExecute , CreateProcess o cualquier versión extendida. Estas API básicamente envuelven otras API de nivel NT que no están documentadas oficialmente. Hasta donde yo sé, estas llamadas envuelven NtCreateProcess , que requiere la estructura OBJECT_ATTRIBUTES como parámetro, para crear esa estructura se usa InitializeObjectAttributes . En este lugar vemos UNICODE_STRING. Así que ahora echemos un vistazo a esta estructura:

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

Utiliza la USHORTvariable (longitud de 16 bits [0; 65535]) para almacenar la longitud. Y de acuerdo con esto , la longitud indica el tamaño en bytes, no en caracteres. Entonces tenemos: 65535 / 2 = 32767(porque WCHARtiene 2 bytes de longitud).

Hay algunos pasos para profundizar en este número, pero espero que esté claro.


Además, para apoyar @sunetos responde lo que se acepta. 8191 es un número máximo que se puede ingresar cmd.exe, si excede este límite, The input line is too long.se genera un error. Entonces, la respuesta es correcta a pesar de que cmd.exeno es la única forma de pasar argumentos para un nuevo proceso.

ST3
fuente
La longitud es de hasta 32.766 caracteres porque se almacena una cadena terminada en nulo.
Eryk Sun
1
Los procesos no se nombran en el espacio de nombres del objeto, por lo ObjectAttributesque solo se usa para el descriptor de seguridad y hace que el identificador devuelto sea heredable. La línea de comando se pasa en ProcessParameters, a la que hace referencia el Bloque de entorno de proceso (PEB). Con el antiguo NtCreateProcess, estos parámetros deben escribirse en el proceso hijo a través de NtWriteVirtualMemory. Hoy en día NtCreateUserProcessse utiliza, que combina varias llamadas a un solo servicio del kernel, por ejemplo Section, la creación de objetos Process, y Thread; y escribir los parámetros del proceso.
Eryk Sun
@eryksun La estructura UNICODE_STRING no almacena necesariamente el terminador nulo.
賈 可 Jacky
@ 賈 可 Jacky, obviamente una cadena contada no necesariamente usa una cadena terminada en nulo. Por ejemplo, con las funciones de registro de NTAPI podemos crear y acceder a nombres de claves con nulos en ellos, pero no serán accesibles con las funciones de registro de WINAPI, que utilizan cadenas terminadas en nulos. Asimismo, WINAPI CreateProcessWusa una cadena terminada en nulo para la línea de comando y la ruta de la aplicación. El límite es 32,767 - 1, es decir, 32,766 caracteres.
Eryk Sun
@eryksun Descubrí que el documento sobre los límites de tamaño de los elementos del registro en MSDN decía que la longitud máxima de un nombre de clave de registro es de 255 caracteres, pero en realidad puede crear un nombre de clave de 256 caracteres. Dado que la cadena de estilo C es solo un puntero sin límite de longitud, supongo que puede ser posible pasar una cadena de 32,767 caracteres a la función Unicode CreateProcessW, puede almacenar la longitud exacta en la UNICODE_STRINGestructura y establecer ambos Lengthy MaximumLengthen 65,534 , es un argumento legal para NtCreateProcess.
賈 可 Jacky
3

En Windows 10, todavía tiene 8191 caracteres ... al menos en mi máquina.

Simplemente corta cualquier texto después de 8191 caracteres. Bueno, en realidad, obtuve 8196 caracteres, y después de 8196, ya no me deja escribir más.

Aquí hay un guión que probará la duración de una declaración que puede usar. Bueno, suponiendo que tengas gawk / awk instalado.

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
fuente
Ese es el límite para cmd.exe. Como dice la respuesta anterior, el límite real es de 32,768 caracteres debido a UNICODE_STRING.
alastair