ความยาวสูงสุดของสตริงบรรทัดคำสั่ง


110

ใน Windows ความยาวสูงสุดของสตริงบรรทัดคำสั่งคืออะไร? หมายถึงถ้าฉันระบุโปรแกรมที่รับอาร์กิวเมนต์ในบรรทัดคำสั่งเช่นabc.exe -name=abc

แอปพลิเคชันคอนโซลอย่างง่ายที่ฉันเขียนรับพารามิเตอร์ผ่านทางบรรทัดคำสั่งและฉันต้องการทราบจำนวนเงินสูงสุดที่อนุญาต


หากใครสนใจฉันกำลังหาวิธีให้โปรแกรมรองรับบรรทัดคำสั่งที่ยาวขึ้น สมมติว่าเราสามารถสร้างการสนับสนุนได้เพียงพอการดำเนินการนี้จะลบข้อ จำกัด ทั้งหมดโดยไม่ต้องให้ Microsoft แก้ไขอะไรเลยและในลักษณะที่เข้ากันได้อย่างตรงไปตรงมา ไม่ใช่คำตอบสำหรับคำถาม แต่ควรมีลิงก์ที่นี่ IMO
alastair

คำตอบ:


87

จากเอกสารของ Microsoft: ข้อ จำกัด สตริงบรรทัดคำสั่ง Command prompt (Cmd. exe)

ในคอมพิวเตอร์ที่ใช้ Microsoft Windows XP หรือใหม่กว่าความยาวสูงสุดของสตริงที่คุณสามารถใช้ได้ที่พรอมต์คำสั่งคือ 8191 อักขระ


33
สิ่งนี้ใช้ได้กับโปรแกรมที่รันผ่านพรอมต์คำสั่งเท่านั้น (ต่อคำถาม) ทางลัด (.lnk) จำกัด ไว้ที่ 260 ตัวอักษร CreateProcess เป็น 32767 และ ShellExecute ถึงประมาณปี 2048 อ้างอิงจากบทความของ Raymond Chen ในหัวข้อ
NtscCobalt

2 ^ 13-1 อักขระซึ่งหมายถึงบางสิ่งบางอย่างถูกติดตามในตัวเลข 16 และใช้ 13 บิตเหล่านั้น ฉันสงสัยว่าอีก 3 บิตมีไว้เพื่ออะไร?
Sqeaky

@ulrichb และตอนนี้ลิงก์นั้นก็ใช้งานไม่ได้เช่นกันหลังจากนั้นก็มีการย้ายบล็อกอีกครั้ง ตอนนี้สามารถดูบทความที่อ้างถึงได้ที่devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553
Adam Rosenfield

72

ขออภัยที่ขุดเจอกระทู้เก่า แต่ฉันคิดว่าคำตอบของ sunetosไม่ถูกต้อง (หรือไม่ใช่คำตอบทั้งหมด) ฉันได้ทำการทดลองบางอย่างแล้ว (โดยใช้ ProcessStartInfo ใน c #) และดูเหมือนว่าสตริง 'อาร์กิวเมนต์' สำหรับคำสั่ง commandline จะ จำกัด ไว้ที่ 2048 อักขระใน XP และ 32768 อักขระใน Win7 ฉันไม่แน่ใจว่าขีด จำกัด 8191 หมายถึงอะไร แต่ฉันยังไม่พบหลักฐานใด ๆ


คุณจะได้รับตัวเลข 32k สำหรับ Win7 มาจากไหน? ฉันหาแหล่งที่มาไม่ได้ คุณกำลังคิดถึงขนาดของบล็อกสภาพแวดล้อมหรือไม่?
ปรากฏ

1
เป็นไปได้. ฉันพบตัวเลข 32k โดยส่งอาร์กิวเมนต์ที่ยาวขึ้นและยาวขึ้นไปยังกระบวนการผ่านคลาส C # ProcessStartInfo มันแสดงข้อยกเว้นหลังจาก 32k
Sugrue

10
@LordTorgamus ขีด จำกัด 32k เกิดจากโครงสร้างUNICODE_STRING (ความยาวสั้น) อ้างอิงจากบทความของ Raymond Chen ในหัวข้อ CMD จำกัด บรรทัดไว้ที่ 8192 อักขระ (ฉันถือว่าการคืนค่า carrage เป็นอักขระสุดท้าย) และ ShellExecuteEx จำกัด เป็น "INTERNET_MAX_URL_LENGTH (ประมาณปี 2048)"
NtscCobalt

1
แล้วภายใต้ PowerShell บน Windows 10 ล่ะ?
Nilzor

1
8191 สำหรับ cmd และสิ่งที่ชอบดูเหมือนจริงมากเพิ่งพบสิ่งนี้เมื่อเรียกใช้คำสั่งที่ยาวมากผ่าน Exec ใน MSBuild
stijn

41

ในฐานะ @Sugrue ฉันกำลังขุดกระทู้เก่า ๆ

เพื่ออธิบายว่าเหตุใดจึงมี 32768 (ฉันคิดว่าควรเป็น 32767 แต่ให้เชื่อว่าผลการทดสอบทดลอง) ข้อ จำกัด ของอักขระที่เราต้องขุดลงใน Windows API

ไม่ว่าคุณจะเปิดโปรแกรมด้วยอาร์กิวเมนต์บรรทัดคำสั่งอย่างไรมันจะไปที่ShellExecute , CreateProcessหรือเวอร์ชันเพิ่มเติมใด ๆ ก็ตาม โดยพื้นฐานแล้ว API เหล่านี้จะรวม API ระดับ NT อื่น ๆ ที่ไม่มีเอกสารเป็นทางการ เท่าที่ฉันรู้การเรียกเหล่านี้ห่อNtCreateProcessซึ่งต้องใช้โครงสร้างOBJECT_ATTRIBUTESเป็นพารามิเตอร์เพื่อสร้างโครงสร้างนั้นใช้InitializeObjectAttributes UNICODE_STRINGในสถานที่แห่งนี้ที่เราเห็น ตอนนี้มาดูโครงสร้างนี้กัน:

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

ใช้USHORTตัวแปร (ความยาว 16 บิต [0; 65535]) เพื่อเก็บความยาว และตามนี้ความยาวระบุขนาดเป็นไบต์ไม่ใช่อักขระ ดังนั้นเราจึงมี: 65535 / 2 = 32767(เพราะWCHARมีความยาว 2 ไบต์)

มีขั้นตอนไม่กี่ขั้นตอนในการเจาะลึกตัวเลขนี้ แต่ฉันหวังว่ามันจะชัดเจน


นอกจากนี้เพื่อสนับสนุน @sunetos ตอบสิ่งที่ยอมรับ 8191 เป็นจำนวนสูงสุดที่อนุญาตให้ป้อนได้cmd.exeหากคุณเกินขีด จำกัด นี้The input line is too long.ข้อผิดพลาดจะถูกสร้างขึ้น ดังนั้นคำตอบจึงถูกต้องแม้ว่าcmd.exeจะไม่ใช่วิธีเดียวที่จะส่งผ่านข้อโต้แย้งสำหรับกระบวนการใหม่


ความยาวสูงสุด 32,766 อักขระเนื่องจากเก็บสตริงที่สิ้นสุดด้วย null
Eryk อาทิตย์

1
กระบวนการไม่ได้ตั้งชื่อในเนมสเปซของออบเจ็กต์ดังนั้นจึงObjectAttributesใช้สำหรับตัวบอกความปลอดภัยเท่านั้นและทำให้หมายเลขอ้างอิงที่ส่งคืนสามารถสืบทอดได้ บรรทัดคำสั่งจะถูกส่งไปในProcessParametersซึ่งอ้างอิงโดย Process Environment Block (PEB) เมื่อใช้แบบเก่าNtCreateProcessพารามิเตอร์เหล่านี้จะต้องถูกเขียนลงในกระบวนการย่อยผ่านทางNtWriteVirtualMemory. ปัจจุบันNtCreateUserProcessมีการใช้งานที่ผสมผสานหลายสายไปยังบริการเคอร์เนลเดียว - เช่นการสร้างSection, ProcessและThreadวัตถุ; และเขียนพารามิเตอร์กระบวนการ
Eryk Sun

@eryksun โครงสร้างUNICODE_STRINGไม่จำเป็นต้องเก็บเทอร์มิเนเตอร์ว่าง
賈可 Jacky

@ 賈可 Jacky เห็นได้ชัดว่าสตริงที่ถูกนับไม่จำเป็นต้องใช้สตริงที่สิ้นสุดด้วยค่าว่าง ตัวอย่างเช่นด้วยฟังก์ชันรีจิสทรี NTAPI เราสามารถสร้างและเข้าถึงชื่อคีย์ที่มีค่า null ได้ แต่จะไม่สามารถเข้าถึงได้ด้วยฟังก์ชันรีจิสทรีของ WINAPI ซึ่งใช้สตริงที่สิ้นสุดด้วยค่า null ในทำนองเดียวกัน WINAPI CreateProcessWใช้สตริงที่สิ้นสุดด้วยค่า null สำหรับบรรทัดคำสั่งและเส้นทางของแอปพลิเคชัน ขีด จำกัด คือ 32,767 - 1 เช่น 32,766 อักขระ
Eryk Sun

@eryksun ฉันพบว่าเอกสารเกี่ยวกับRegistry Element Size Limitsบน MSDN กล่าวว่าความยาวสูงสุดของชื่อคีย์รีจิสทรีคือ 255 อักขระ แต่จริงๆแล้วคุณสามารถสร้างชื่อคีย์ได้ 256 อักขระ เนื่องจากสตริงสไตล์ C เป็นเพียงตัวชี้ที่ไม่มีขีดจำกัดความยาวดังนั้นฉันจึงเดาว่าอาจเป็นไปได้ที่จะส่งสตริง 32,767 อักขระไปยังฟังก์ชัน Unicode CreateProcessWมันอาจเก็บความยาวที่แน่นอนไว้ในUNICODE_STRINGโครงสร้างและตั้งค่าทั้งสองLengthและMaximumLengthเป็น 65,534 NtCreateProcessมันเป็นข้อโต้แย้งทางกฎหมายสำหรับ
賈可 Jacky

3

ใน Windows 10 ยังคงเป็นอักขระ 8191 ตัว ... อย่างน้อยก็ในเครื่องของฉัน

เพียงแค่ตัดข้อความใด ๆ หลังจาก 8191 อักขระ ที่จริงฉันมีอักขระ 8196 ตัวและหลังจาก 8196 แล้วมันจะไม่ให้ฉันพิมพ์อีกต่อไป

นี่คือสคริปต์ที่จะทดสอบระยะเวลาที่คุณสามารถใช้คำสั่งได้ สมมติว่าคุณติดตั้ง 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

นั่นคือขีด จำกัด สำหรับ cmd.exe ดังที่คำตอบด้านบนระบุว่าขีด จำกัด ที่แท้จริงคือ 32,768 อักขระเนื่องจาก UNICODE_STRING
alastair
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.