命令行字符串的最大长度

134

在Windows中,命令行字符串的最大长度是多少?也就是说,如果我指定一个需要在命令行上使用参数的程序,例如abc.exe -name=abc

我编写了一个简单的控制台应用程序通过命令行接受参数,现在我想知道允许的最大数量是多少。


答案:

在Windows中,命令行字符串的最大长度为8191个字符。这包括命令本身以及任何传递给该命令的参数。请注意,这里所说的字符数限制特指ANSI字符集中的字符数,而不是Unicode字符集中的字符数。


如果有人感兴趣,我一直在研究程序支持更长命令行的方法。假设我们能够为此建立足够的支持,这将完全消除限制,而无需要求微软修复任何东西,并且以一种简单兼容的方式进行。虽然不是问题的答案,但在这里放一个链接还是值得的。 - al45tair
4个回答

105

46
这仅适用于实际通过命令提示符运行的程序(根据问题)。 快捷方式(.lnk)的长度限制为260个字符,CreateProcess为32767个字符,ShellExecute约为2048个字符。[根据雷蒙德·陈(Raymond Chen)在此主题上的文章](http://blogs.msdn.com/b/oldnewthing/archive/2003/12/10/56028.aspx) - NtscCobalt
2^13-1个字符,这意味着在16个数字中跟踪了某些内容,并且使用了其中的13位。我想知道其他3位是用来做什么的? - Sqeaky
4
现在这个链接也已经失效了,经历了另一次博客迁移。引用的文章现在可以在https://devblogs.microsoft.com/oldnewthing/20031210-00/?p=41553找到。 - Adam Rosenfield
1
现在Windows 11和新的Windows终端都有什么限制?希望它们已经增加了。将成千上万个具有长路径的文件传递给CMake需要占用几兆字节。应该是无限的。 - Lothar
@AdamRosenfield 微软因为毫无理由地破坏了大量链接,不仅是博客,还有关键文档,真应该受到谴责。感谢您的更新。 - Mark Ransom

76

抱歉挖掘了一个老帖子,但我认为 sunetos 的回答 不正确(或不是完整的答案)。我做了一些实验(使用 c# 中的 ProcessStartInfo),似乎在 XP 中命令行命令的“参数”字符串限制为 2048 个字符,在 Win7 中为 32768 个字符。我不确定 8191 的限制指的是什么,但我还没有找到任何证据。


1
可能是这样。我通过使用C# ProcessStartInfo类向进程传递越来越长的参数来找到32k的数字。在32k后,它会抛出异常。 - Sugrue
14
@LordTorgamus,32k限制的原因是由于UNICODE_STRING结构(ushort长度)。根据雷蒙德·陈在这个主题上的文章,在CMD中限制每行字符数为8192(我会假设回车符是最后一个字符),而ShellExecuteEx则限制为“INTERNET_MAX_URL_LENGTH(大约2048)”。 - NtscCobalt
5
在Windows 10上使用PowerShell呢? - Nilzor
2
8191对于cmd和类似的工具来说似乎非常真实,当我通过MSBuild中的Exec运行一个非常长的命令时就遇到了这个问题。 - stijn
@Contango 你试过使用WinTerminal而不是cmd.exe吗?我希望它不会那么有限。 - Lothar
显示剩余3条评论

52

像@Sugrue一样,我也正在挖掘一条旧线程。

为了解释为什么有32768(我认为应该是32767,但让我们相信实验测试结果)个字符的限制,我们需要深入研究Windows API。

无论您如何使用命令行参数启动程序,它都会进入ShellExecuteCreateProcess或任何扩展版本。这些API基本上包装了其他未被官方记录的NT级API。据我所知,这些调用包装了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的答案,最大允许输入cmd.exe的数字是8191,如果超过此限制,则会生成输入行太长错误。 因此,尽管cmd.exe不是传递新进程参数的唯一方式,但答案是正确的。


4
由于存储了以空字符结尾的字符串,长度可达32,766个字符。 - Eryk Sun
1
进程在对象名称空间中没有名称,因此“ObjectAttributes”仅用于安全描述符和使返回的句柄可继承。命令行传递给“ProcessParameters”,该参数由进程环境块(PEB)引用。使用旧的“NtCreateProcess”,必须通过“NtWriteVirtualMemory”将这些参数写入子进程。现在使用“NtCreateUserProcess”,它将几个调用结合到单个内核服务中--例如创建“Section”、“Process”和“Thread”对象;并编写进程参数。 - Eryk Sun
1
@賈可Jacky,显然计数字符串不一定使用以空字符结尾的字符串。例如,使用NTAPI注册表函数可以创建和访问包含空字符的键名,但是使用以空字符结尾的字符串的WINAPI注册表函数无法访问它们。同样,WINAPI CreateProcessW 对于命令行和应用程序路径使用以空字符结尾的字符串。限制为32,767-1,即32,766个字符。 - Eryk Sun
@賈可Jacky,為什麼要猜測呢?不如寫一個快速的測試程式來檢測這個問題。這也是我最初所做的。32,767個字元的命令列會出現“ERROR_FILENAME_EXCED_RANGE”(206)錯誤。這是從內部呼叫“RtlInitUnicodeStringEx”(NT5.2+)引起的,它要求初始化字符串是一個空結尾字符串,長度不超過“UNICODE_STRING_MAX_CHARS - 1”,即32,766個字符。較舊的Windows版本調用“RtlInitUnicodeString”,它會天真地假設長度有效,如果不是,就返回荒唐的數值,如“Length == 32767”和“MaximumLength == 0”(溢出)。 - Eryk Sun
@eryksun 谢谢!我从未测试过它。 - xenophōn
显示剩余3条评论

9
在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

2
这是cmd.exe的限制。正如上面的答案所说,由于UNICODE_STRING的存在,实际限制为32,768个字符。 - al45tair
在cmd.exe中,我在Windows 10和Windows Server 2019上都遇到了大约8k的限制。 - fantabolous

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接