Maksimum Komut Satırı Dizesi Uzunluğu


110

Windows'ta bir komut satırı dizesinin maksimum uzunluğu nedir? Bunun anlamı, komut satırında aşağıdaki gibi argümanlar alan bir program belirtirsemabc.exe -name=abc

Yazdığım basit bir konsol uygulaması, komut satırı aracılığıyla parametreleri alıyor ve izin verilen maksimum miktarın ne olduğunu bilmek istiyorum.


İlgilenen varsa, programların daha uzun komut satırlarını desteklemesi için bir yol üzerinde çalışıyorum . Bunun için yeterli desteği oluşturabileceğimizi varsayarsak, bu, Microsoft'un herhangi bir şeyi düzeltmesini gerektirmeden ve doğrudan uyumlu bir şekilde kısıtlamaları tamamen kaldıracaktır. Aslında sorunun cevabı değil, IMO burada bir bağlantıya sahip olmaya değer.
alastair

Yanıtlar:


87

Microsoft belgelerinden: Komut istemi (Cmd. Exe) komut satırı dizesi sınırlaması

Microsoft Windows XP veya sonraki sürümünü çalıştıran bilgisayarlarda, komut isteminde kullanabileceğiniz maksimum dize uzunluğu 8191 karakterdir.


33
Bu, yalnızca komut isteminde (soru başına) gerçekten çalışan programlar için geçerlidir. Kısayollar (.lnk) 260 karakter, CreateProcess 32767 ve ShellExecute yaklaşık 2048 karakterle sınırlıdır. Raymond Chen'in konuyla ilgili makalesine göre
NtscCobalt

2 ^ 13-1 karakter, bir şeyin 16 sayı içinde izlendiğini ve bu bitlerin 13'ünü kullandığını gösterir. Diğer 3 bit ne için acaba?
Sqeaky

@ulrichb Ve şimdi bu bağlantı başka bir blog geçişinden sonra da koptu. Alıntılanan
Adam Rosenfield

72

Eski bir konuyu kazdığım için üzgünüm, ama sanırım sunetos'un cevabı doğru değil (veya tam cevap değil). Bazı deneyler yaptım (c # 'da ProcessStartInfo kullanarak) ve bir komut satırı komutu için' arguments 'dizesinin XP'de 2048 karakter ve Win7'de 32768 karakterle sınırlı olduğu görülüyor. 8191 sınırının ne anlama geldiğinden emin değilim, ancak henüz bir kanıt bulamadım.


Win7 için 32k rakamını nereden buldunuz? Bunun için bir kaynak bulamıyorum. Çevre bloğunun boyutunu düşünüyor musunuz ?
Pops

1
Muhtemelen. C # ProcessStartInfo sınıfı aracılığıyla bir sürece daha uzun ve daha uzun argümanlar ileterek 32k rakamını buldum. 32k sonra bir istisna atar.
09

10
@LordTorgamus, 32k sınırı UNICODE_STRING yapısından (ushort uzunluğu) kaynaklanmaktadır. Raymond Chen'in konu hakkındaki makalesine göre CMD, satırları 8192 karakterle sınırlandırıyor (carrage dönüşünün son karakter olduğunu varsayıyorum) ve ShellExecuteEx, "INTERNET_MAX_URL_LENGTH (yaklaşık 2048)" ile
sınırlanıyor

1
Windows 10'da PowerShell altında ne olacak?
Nilzor

1
Cmd için 8191 ve benzerleri çok gerçek görünüyor,
MSBuild'de

41

@ Sugrue olarak eski bir konuyu da kazıyorum.

Neden 32768 (32767 olması gerektiğini düşünüyorum, ancak deneysel test sonucuna inanalım) karakter sınırlamasının neden olduğunu açıklamak için Windows API'yi araştırmamız gerekiyor.

Programı komut satırı argümanları ile nasıl başlattığınız önemli değil, program ShellExecute , CreateProcess veya herhangi bir genişletilmiş sürümüne gider . Bu API'ler temelde resmi olarak belgelenmemiş diğer NT seviyesi API'leri sarar. Gibi bildiğim kadarıyla bu çağrıları sarın NtCreateProcess gerektirir OBJECT_ATTRIBUTES o yapı oluşturmak için, bir parametre olarak yapısını InitializeObjectAttributes kullanılır. Bu yerde görüyoruz UNICODE_STRING. Şimdi bu yapıya bir göz atalım:

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

USHORTUzunluğu saklamak için (16-bit uzunluk [0; 65535]) değişkenini kullanır. Ve göre bu , uzunluk bayt karakter değil cinsinden boyutunu belirtir. Elimizde: 65535 / 2 = 32767(çünkü WCHAR2 bayt uzunluğunda).

Bu numarayı araştırmak için birkaç adım var, ancak umarım açıktır.


Ayrıca @sunetos'u desteklemek için neyin kabul edildiğini yanıtlayın. 8191, girilmesine izin verilen maksimum sayıdır cmd.exe, bu sınırı aşarsanız, The input line is too long.hata oluşturulur. Dolayısıyla, cmd.exeyeni süreç için argümanlar iletmenin tek yolu bu olmasa da cevap doğrudur .


Uzunluk 32.766 karaktere kadardır, çünkü boş sonlandırılmış bir dizge saklanır.
Eryk Sun

1
İşlemler nesne ad alanında adlandırılmaz, bu nedenle ObjectAttributesyalnızca güvenlik tanımlayıcısı için kullanılır ve döndürülen tutamacı devralınabilir hale getirir. Komut satırı, ProcessParametersİşlem Ortamı Bloğu (PEB) tarafından referans verilen içinde iletilir . Eskisi ile NtCreateProcess, bu parametreler alt sürece yazılmalıdır NtWriteVirtualMemory. Günümüzde NtCreateUserProcessçok sayıda tek bir çekirdek hizmeti çağrıları birleştiren kullanılır, - örneğin oluşturma Section, Processve Threadnesnelerin; ve işlem parametrelerinin yazılması.
Eryk Sun

@eryksun UNICODE_STRING yapısı, boş sonlandırıcı depolamak zorunda değildir.
賈 可 Jacky

@ 賈 可 Jacky, belli ki sayılan bir dizge mutlaka boş sonlu bir dizge kullanmaz. Örneğin, NTAPI kayıt işlevleriyle, içlerinde boş olan anahtar adları oluşturabilir ve bunlara erişebiliriz, ancak bunlara boş sonlandırılmış dizeler kullanan WINAPI kayıt işlevleri ile erişilemez. Aynı şekilde WINAPI CreateProcessW, komut satırı ve uygulama yolu için boş sonlandırılmış bir dize kullanır. Sınır 32.767 - 1, yani 32.766 karakterdir.
Eryk Sun

@eryksun MSDN'de Kayıt Defteri Öğesi Boyut Sınırları hakkındaki belgede bir kayıt defteri anahtarı adının maksimum uzunluğunun 255 karakter olduğunu, ancak aslında 256 karakterlik bir anahtar adı oluşturabileceğinizi öğrendim . C-stili dizge, uzunluk sınırı olmayan bir işaretçi olduğundan, bu nedenle, 32.767 karakterlik bir diziyi unicode işlevine geçirmenin mümkün olabileceğini tahmin ediyorum CreateProcessW, UNICODE_STRINGyapıda tam uzunluğu depolayabilir ve hem Lengthve hem de MaximumLength65.534 olarak ayarlayabilir. için yasal bir argümandır NtCreateProcess.
賈 可 Jacky

3

Windows 10'da hala 8191 karakter ... en azından benim makinemde.

Sadece 8191 karakterden sonra herhangi bir metni keser. Aslında, 8196 karakterim var ve 8196'dan sonra, artık yazmama izin vermiyor.

İşte bir ifadenin ne kadar süreyle kullanabileceğinizi test edecek bir komut dosyası. Peki, gawk / awk kurulu olduğunu varsayarsak.

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

Cmd.exe için sınır budur. Yukarıdaki yanıtın da belirttiği gibi, gerçek sınır UNICODE_STRING nedeniyle 32.768 karakterdir.
alastair
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.