Comprimento máximo da string da linha de comando

110

No Windows, qual é o comprimento máximo de uma string de linha de comando? Ou seja, se eu especificar um programa que recebe argumentos na linha de comando, comoabc.exe -name=abc

Um aplicativo de console simples que escrevi usa parâmetros via linha de comando e quero saber qual é a quantidade máxima permitida.

ST3
fonte
Se alguém estiver interessado, estou trabalhando em uma maneira de os programas suportarem linhas de comando mais longas . Presumindo que possamos construir suporte suficiente para isso, isso removeria as restrições completamente sem exigir que a Microsoft corrija nada e de uma maneira que seja totalmente compatível. Não é bem uma resposta para a pergunta, mas vale a pena ter um link aqui IMO.
Alastair

Respostas:

87

Na documentação da Microsoft: Limitação da string de linha de comando do prompt de comando (cmd. Exe)

Em computadores que executam o Microsoft Windows XP ou posterior, o comprimento máximo da string que você pode usar no prompt de comando é 8191 caracteres.

sunetos
fonte
33
Isso se aplica apenas aos programas realmente executados por meio do prompt de comando (de acordo com a pergunta). Os atalhos (.lnk) são limitados a 260 caracteres, CreateProcess a 32767 e ShellExecute a cerca de 2048. De acordo com o artigo de Raymond Chen sobre o assunto
NtscCobalt
2 ^ 13-1 caracteres, o que implica que algo é rastreado em um número de 16 e isso usa 13 desses bits. Eu me pergunto para que servem os outros 3 bits?
Sqeaky
@ulrichb E agora esse link também foi quebrado após mais uma migração do blog. O artigo citado agora pode ser encontrado em devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
Adam Rosenfield
72

Desculpe por explorar um tópico antigo, mas acho que a resposta de sunetos não está correta (ou não é a resposta completa). Eu fiz alguns experimentos (usando ProcessStartInfo em c #) e parece que a string de 'argumentos' para um comando de linha de comando é limitada a 2.048 caracteres no XP e 32768 caracteres no Win7. Não tenho certeza a que se refere o limite de 8191, mas ainda não encontrei nenhuma evidência disso.

Sugrue
fonte
Onde você conseguiu a figura de 32k para Win7? Não consigo encontrar uma fonte para isso. Você está pensando no tamanho do bloco de ambiente ?
Aparece em
1
Possivelmente. Eu encontrei a figura de 32k passando argumentos cada vez mais longos para um processo por meio da classe C # ProcessStartInfo. Ele lança uma exceção após 32k.
Sugrue,
10
@LordTorgamus, O limite 32k é devido ao UNICODE_STRING estrutura (comprimento ushort). De acordo com o artigo de Raymond Chen sobre o assunto, o CMD limita as linhas a 8.192 caracteres (presumo que o retorno da carragem é o caractere final) e o ShellExecuteEx limita a "INTERNET_MAX_URL_LENGTH (por volta de 2048)"
NtscCobalt
1
E no PowerShell no Windows 10?
Nilzor
1
8191 para cmd e similares parece muito real, apenas encontrei isso ao executar um comando muito longo via Exec no MSBuild
stijn
41

Como @Sugrue, também estou descobrindo um tópico antigo.

Para explicar por que há 32.768 (acho que deveria ser 32.767, mas vamos acreditar no resultado do teste experimental) limitação de caracteres, precisamos examinar a API do Windows.

Não importa como você inicia o programa com argumentos de linha de comando, ele vai para ShellExecute , CreateProcess ou qualquer versão estendida. Essas APIs basicamente envolvem outras APIs de nível NT que não estão oficialmente documentadas. Pelo que eu sei, essas chamadas envolvem NtCreateProcess , que requer a estrutura OBJECT_ATTRIBUTES como um parâmetro, para criar essa estrutura InitializeObjectAttributes é usada. Neste lugar nós vemos UNICODE_STRING. Então, agora vamos dar uma olhada nesta estrutura:

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

Ele usa USHORTa variável (comprimento de 16 bits [0; 65535]) para armazenar o comprimento. E, de acordo com isso , o comprimento indica o tamanho em bytes, não em caracteres. Portanto, temos: 65535 / 2 = 32767(porque WCHARtem 2 bytes de comprimento).

Existem algumas etapas para analisar esse número, mas espero que esteja claro.


Além disso, para apoiar @sunetos responda o que é aceito. 8191 é um número máximo permitido para ser inserido cmd.exe, se você exceder esse limite, um The input line is too long.erro será gerado. Portanto, a resposta está correta apesar de cmd.exenão ser a única forma de passar argumentos para um novo processo.

ST3
fonte
O comprimento é de até 32.766 caracteres porque uma string terminada em nulo é armazenada.
Eryk Sun
1
Os processos não são nomeados no namespace do objeto, portanto, o ObjectAttributesé usado apenas para o descritor de segurança e torna o identificador retornado herdável. A linha de comando é passada no ProcessParameters, que é referenciado pelo Process Environment Block (PEB). Com o antigo NtCreateProcess, esses parâmetros devem ser gravados no processo filho via NtWriteVirtualMemory. Hoje em dia NtCreateUserProcessé usado, o que combina várias chamadas para um único serviço de kernel - por exemplo Section, criando Process, e Threadobjetos; e escrever os parâmetros do processo.
Eryk Sun
@eryksun A estrutura UNICODE_STRING não armazena necessariamente o terminador nulo.
賈 可 Jacky
@ 賈 可 Jacky, obviamente uma string contada não usa necessariamente uma string terminada em nulo. Por exemplo, com as funções de registro NTAPI, podemos criar e acessar nomes de chave com nulos, mas eles não serão acessíveis com funções de registro WINAPI, que usam strings terminadas em nulo. Da mesma forma, o WINAPI CreateProcessWusa uma string terminada em nulo para a linha de comando e o caminho do aplicativo. O limite é 32.767-1, ou seja, 32.766 caracteres.
Eryk Sun
@eryksun Descobri que o documento sobre Limites de Tamanho do Elemento de Registro no MSDN dizia que o comprimento máximo de um nome de chave de registro é de 255 caracteres, mas na verdade você pode criar um nome de chave de 256 caracteres. Já que a string de estilo C é apenas um ponteiro sem limite de comprimento, então eu acho que pode ser possível passar uma string de 32.767 caracteres para a função unicode CreateProcessW, ela pode armazenar o comprimento exato na UNICODE_STRINGestrutura e definir tanto Lengthcomo MaximumLength65.534 , é um argumento legal para NtCreateProcess.
賈 可 Jacky
3

No Windows 10, ainda são 8.191 caracteres ... pelo menos na minha máquina.

Ele apenas corta qualquer texto após 8.191 caracteres. Bem, na verdade, eu tenho 8.196 caracteres, e depois de 8.196, ele simplesmente não me deixa digitar mais.

Aqui está um script que testará a extensão de uma instrução que você pode usar. Bem, supondo que você tenha o 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
fonte
Esse é o limite para cmd.exe. Como a resposta acima diz, o limite real é de 32.768 caracteres por causa de UNICODE_STRING.
Alastair