记录一下Windows系统下的命令行参数的字符个数限制

记得在三年前,我们在做应用升级,选型了通过启动传参的方式,客户端通过传递参数给更新器 参数,执行应用升级。一开始更新的应用不多,参数的字符个数也是在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

相关推荐
李小咖19 天前
第2章 cmd命令基础:常用基础命令(1)
windows·网络安全·cmd·cmd命令·李小咖
IT成长日记1 个月前
【Docker基础】Dockerfile指令速览:基础常用指令详解
docker·容器·dockerfile·cmd·copy·from·run
spencer_tseng1 个月前
Windows DOS CMD 100
windows·dos·cmd
集成显卡2 个月前
图片压缩工具 | Electron应用配合 commander 提供命令行调用功能
前端·javascript·electron·人机交互·命令行·cmd
188_djh3 个月前
# 终端执行 java -jar example.jar 时(example.jar为项目jar包)报错:“没有主清单属性” 的解决方法
java·pycharm·jar·cmd·没有主清单属性·java -jar
胡斌附体3 个月前
设置环境变量启动jar报
java·jar·cmd·path
wsdhla4 个月前
如何在Windows上实现MacOS中的open命令
mac·cmd·open
Bruce_Liuxiaowei4 个月前
[特殊字符]fsutil命令用法详解
windows·cmd
Ven%4 个月前
如何让老电脑运行快些(极限榨干老电脑硬件)
windows·电脑·cmd