Độ dài tối đa của chuỗi dòng lệnh


110

Trong Windows, độ dài tối đa của một chuỗi dòng lệnh là bao nhiêu? Có nghĩa là nếu tôi chỉ định một chương trình lấy các đối số trên dòng lệnh, chẳng hạn nhưabc.exe -name=abc

Một ứng dụng console đơn giản mà tôi đã viết lấy các tham số thông qua dòng lệnh và tôi muốn biết số lượng tối đa cho phép là bao nhiêu.


Nếu ai đó quan tâm, tôi đang tìm cách để các chương trình hỗ trợ các dòng lệnh dài hơn . Giả sử chúng ta có thể xây dựng đủ hỗ trợ cho nó, điều này sẽ loại bỏ hoàn toàn các hạn chế mà không yêu cầu Microsoft sửa bất cứ điều gì và theo cách tương thích dễ dàng. Không thực sự là một câu trả lời cho câu hỏi, nhưng đáng để có một liên kết ở đây IMO.
alastair

Câu trả lời:


87

Từ tài liệu của Microsoft: Giới hạn chuỗi dòng lệnh của Command Prompt (Cmd. Exe)

Trên máy tính chạy Microsoft Windows XP trở lên, độ dài tối đa của chuỗi mà bạn có thể sử dụng tại dấu nhắc lệnh là 8191 ký tự.


33
Điều này chỉ áp dụng cho các chương trình thực sự chạy qua dấu nhắc lệnh (theo câu hỏi). Phím tắt (.lnk) được giới hạn 260 ký tự, CreateProcess để 32767, và ShellExecute đến khoảng 2048. Theo bài báo của Raymond Chen về đề tài này
NtscCobalt

2 ^ 13-1 ký tự, có nghĩa là một cái gì đó được theo dõi trong số 16 và điều này sử dụng 13 trong số các bit đó. Không biết 3 bit kia dùng để làm gì?
Sqeaky

@ulrichb Và bây giờ liên kết đó cũng bị hỏng sau một lần di chuyển blog khác. Bài báo được trích dẫn hiện có thể được tìm thấy tại devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
Adam Rosenfield

72

Xin lỗi vì đã đào ra một chủ đề cũ, nhưng tôi nghĩ câu trả lời của sunetos không đúng (hoặc không phải là câu trả lời đầy đủ). Tôi đã thực hiện một số thử nghiệm (sử dụng ProcessStartInfo trong c #) và có vẻ như chuỗi 'đối số' cho một lệnh dòng lệnh bị giới hạn ở 2048 ký tự trong XP và 32768 ký tự trong Win7. Tôi không chắc giới hạn 8191 đề cập đến điều gì, nhưng tôi chưa tìm thấy bất kỳ bằng chứng nào về nó.


Bạn lấy con số 32k cho Win7 ở đâu? Tôi không thể tìm thấy một nguồn cho điều đó. Bạn đang nghĩ về kích thước của khối môi trường ?
Pops

1
Có khả năng. Tôi đã tìm thấy con số 32k bằng cách truyền các đối số dài hơn và dài hơn cho một quy trình thông qua lớp C # ProcessStartInfo. Nó ném ra một ngoại lệ sau 32k.
Sugrue

10
@LordTorgamus, Giới hạn 32k là do sự UNICODE_STRING cấu trúc (chiều dài ushort). Theo bài báo của Raymond Chen về chủ đề CMD giới hạn dòng để 8192 ký tự (tôi giả định sự trở lại carrage là nhân vật cuối cùng) và giới hạn ShellExecuteEx để "INTERNET_MAX_URL_LENGTH (khoảng 2048)"
NtscCobalt

1
Còn trong PowerShell trên Windows 10 thì sao?
Nilzor

1
8191 cho cmd và thích dường như rất thực tế, chỉ cần chạy vào này khi chạy một lệnh rất dài qua Exec trong MSBuild
Stijn

41

Như @Sugrue, tôi cũng đang tìm một chủ đề cũ.

Để giải thích tại sao có giới hạn ký tự 32768 (tôi nghĩ nó phải là 32767, nhưng hãy tin vào kết quả kiểm tra thử nghiệm), chúng ta cần tìm hiểu kỹ về Windows API.

Bất kể bạn khởi chạy chương trình bằng các đối số dòng lệnh như thế nào, nó sẽ chuyển đến ShellExecute , CreateProcess hoặc bất kỳ phiên bản mở rộng nào của chúng. Các API này về cơ bản bao bọc các API cấp NT khác không được ghi nhận chính thức. Theo như tôi biết các cuộc gọi này bao bọc NtCreateProcess , yêu cầu cấu trúc OBJECT_ATTRIBUTES làm tham số, để tạo cấu trúc đó thì dùng InitializeObjectAttributes . Ở nơi này chúng ta thấy UNICODE_STRING. Vì vậy, bây giờ chúng ta hãy xem xét cấu trúc này:

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

Nó sử dụng biến USHORT(độ dài 16-bit [0; 65535]) để lưu trữ độ dài. Và theo điều này , chiều dài cho biết kích thước tính bằng byte, không phải ký tự. Vì vậy, chúng ta có: 65535 / 2 = 32767(vì WCHARdài 2 byte).

Có một vài bước để tìm hiểu con số này, nhưng tôi hy vọng nó rõ ràng.


Ngoài ra, để hỗ trợ @sunetos trả lời những gì được chấp nhận. 8191 là số tối đa được phép nhập vào cmd.exe, nếu bạn vượt quá giới hạn này, The input line is too long.lỗi sẽ được tạo ra. Vì vậy, câu trả lời là đúng mặc dù thực tế đó cmd.exekhông phải là cách duy nhất để chuyển các đối số cho quy trình mới.


Độ dài lên đến 32,766 ký tự vì một chuỗi kết thúc bằng null được lưu trữ.
Eryk Sun

1
Các quy trình không được đặt tên trong không gian tên đối tượng, do đó, quy trình ObjectAttributeschỉ được sử dụng cho bộ mô tả bảo mật và làm cho xử lý trả về có thể kế thừa. Dòng lệnh được chuyển vào ProcessParameters, được tham chiếu bởi Khối Môi trường Quy trình (PEB). Với cái cũ NtCreateProcess, các tham số này phải được ghi vào process con thông qua NtWriteVirtualMemory. Ngày nay NtCreateUserProcessđược sử dụng, trong đó kết hợp một số cuộc gọi đến một dịch vụ hạt nhân duy nhất - ví dụ như việc tạo Section, ProcessThreadđối tượng; và viết các thông số quy trình.
Eryk Sun

@eryksun Các UNICODE_STRING cấu trúc không nhất thiết phải lưu trữ vô terminator.
賈 可 Jacky

@ 賈 可 Jacky, rõ ràng là một chuỗi được đếm không nhất thiết phải sử dụng một chuỗi kết thúc bằng rỗng. Ví dụ: với các hàm đăng ký NTAPI, chúng ta có thể tạo và truy cập vào các tên khóa có null, nhưng chúng sẽ không thể truy cập được với các hàm đăng ký WINAPI, sử dụng các chuỗi được kết thúc bằng null. Tương tự như vậy, WINAPI CreateProcessWsử dụng một chuỗi kết thúc bằng null cho dòng lệnh và đường dẫn ứng dụng. Giới hạn là 32,767 - 1, tức là 32,766 ký tự.
Eryk Sun

@eryksun Tôi thấy rằng tài liệu về Giới hạn kích thước phần tử đăng ký trên MSDN cho biết độ dài tối đa của tên khóa đăng ký là 255 ký tự, nhưng thực tế bạn có thể tạo tên khóa gồm 256 ký tự. Vì chuỗi kiểu C chỉ là một con trỏ không có giới hạn độ dài, vì vậy tôi đoán rằng có thể chuyển một chuỗi gồm 32,767 ký tự vào hàm unicode CreateProcessW, nó có thể lưu trữ độ dài chính xác trong UNICODE_STRINGcấu trúc và đặt cả hai LengthMaximumLengththành 65,534 , nó là một đối số pháp lý cho NtCreateProcess.
賈 可 Jacky

3

Trong Windows 10, nó vẫn là 8191 ký tự ... ít nhất là trên máy của tôi.

Nó chỉ cắt bỏ bất kỳ văn bản nào sau 8191 ký tự. Thực ra thì, tôi đã có 8196 ký tự, và sau 8196, nó sẽ không cho phép tôi gõ thêm nữa.

Đây là một tập lệnh sẽ kiểm tra thời lượng của một câu lệnh mà bạn có thể sử dụng. Giả sử bạn đã cài đặt 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

Đó là giới hạn cho cmd.exe. Như câu trả lời ở trên cho biết, giới hạn thực tế là 32.768 ký tự do UNICODE_STRING.
alastair
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.