记得在三年前,我们在做应用升级,选型了通过启动传参的方式,客户端通过传递参数给更新器 参数,执行应用升级。一开始更新的应用不多,参数的字符个数也是在1000以内,没有发现问题。后来随着全家桶应用的新增,应用个数越来越多,直到在一个测试升级的时候,测试手动写了一万多个字符的更新的描述。执行升级直接异常了。
1、查阅了微软的官方文档,命令提示符行字符串限制 - Windows Client | Microsoft Learn,有如下的说明:
以下示例演示如何将此限制应用于在命令提示符中运行的命令以及批处理文件中使用的命令。
-
在命令提示符中,以下命令行的总长度不能超过 8191 个字符:
cmd.exe /k ExecutableFile.exe parameter1, parameter2... parameterN
-
在批处理文件中,以下命令行的总长度不能超过 8191 个字符:
cmd.exe /k ExecutableFile.exe parameter1, parameter2... parameterN
-
此限制适用于使用命令提示符运行批处理文件时包含在批处理文件中的命令行。
-
在命令提示符中,展开
EnvironmentVariable2``EnvironmentVariable3
后的总长度EnvironmentVariable1
不能超过 8191 个字符:c:> set EnvironmentVariable1 = EnvironmentVariable2 EnvironmentVariable3
-
在批处理文件中,展开参数后以下命令行的总长度不能超过 8191 个字符:
ExecutableFile.exe parameter1 parameter2
-
尽管环境变量的 Win32 限制为 32,767 个字符,但命令提示符会忽略从父进程继承的任何环境变量,并且比自身限制 8191 个字符(适用于操作系统)长。 有关函数
SetEnvironmentVariable
的详细信息,请参阅 SetEnvironmentVariableA 函数。
2、准备工作:先实现一个控制台程序 CmdConsoleApp,供进程启动调用
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
if (args.Length <= 0)
{
Console.WriteLine($"没有输入参数");
return;
}
Console.WriteLine($"输入参数个数: {args.Length}");
foreach (var arg in args)
{
Console.WriteLine($"参数为: {arg}");
Console.WriteLine($"参数的长度为:{arg.Length}");
}
3、对于以上的微软官网的说明,我们使用的方式是父进程启动子进程的方式,给升级器进程传递参数的,这个限制是由操作系统的CreateProcess函数决定的也就是总长度不能超过 32,767字符长度,代码如下:
// See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using System.Text;
var cmdConsoleAppPath = @$"E:\Code\wutyDemo\CmdConsoleApp\bin\Debug\net8.0\CmdConsoleApp.exe";
var pathLength = cmdConsoleAppPath.Length;
StringBuilder sb = new StringBuilder();
var count = 32767 - pathLength;
sb = new StringBuilder();
for (int i = 0; i < count; i++)
{
sb.Append("1");
}
Process.Start(cmdConsoleAppPath, sb.ToString());
3.1、执行结果如下,直接报文件名太长:

3.2、如果适当调低打印的总的个数参数,如 32763的个数,是可以正常打印:

4、cmd 控制台命令行参数:从上方的官方文档可以看出,如果调用 cmd.exe 的方式,命令行的总长度不能超过 8191 个字符
// See https://aka.ms/new-console-template for more information
using System.Diagnostics;
using System.Text;
var cmdConsoleAppPath = @$"E:\Code\wutyDemo\CmdConsoleApp\bin\Debug\net8.0\CmdConsoleApp.exe";
var pathLength = cmdConsoleAppPath.Length;
StringBuilder sb = new StringBuilder();
var cmdFileName = "cmd.exe";
var processArgs1 = $"/k {cmdConsoleAppPath} ";
var cmdParmamterCount = 8191 - cmdFileName.Length - processArgs1.Length;
for (int i = 0; i < cmdParmamterCount; i++)
{
sb.Append("1");
}
processArgs1 += sb.ToString();
using Process process = new Process();
// 2. 配置启动信息
process.StartInfo = new ProcessStartInfo
{
FileName = cmdFileName, // 调用命令提示符
Arguments = processArgs1, // 执行命令参数
};
process.Start();
4.1、控制台打印如下图所示:

4**.2、如果适当调低打印的总的个数参数,如 8188的个数,是可以正常打印:**

5、如何解决限制
若要解决此限制,请根据情况使用以下一个或多个方法:
-
修改需要长命令行的程序,以便它们使用包含参数信息的文件,然后在命令行中包含文件的名称。
例如,不要在批处理文件中使用
ExecutableFile.exe Parameter1 Parameter2... ParameterN
命令行,而是修改程序以使用类似于以下命令行的命令行,其中 ParameterFile 是包含所需参数的文件(parameter1 parameter2...ParameterN):ExecutableFile.exe c:\temp\ParameterFile.txt
-
修改使用大型环境变量的程序,以便环境变量包含少于 8191 个字符。
例如,如果 PATH 环境变量包含的字符数超过 8191 个字符,请使用以下一个或多个方法来减少字符数:
- 对文件夹和文件使用较短的名称。
- 减少文件夹树的深度。
- 将文件存储在较少的文件夹中,以便 PATH 环境变量中需要更少的文件夹。
-
调查可用于减少 PATH 依赖项以查找.dll文件可能的方法。
参考文档:
命令提示符行字符串限制 - Windows Client | Microsoft Learn