Giới hạn độ dài tham số dòng lệnh trong hệ điều hành Windows

Trong quá trình nâng cấp ứng dụng cách đây ba năm, chúng tôi đã lựa chọn phương pháp truyền tham số để thực hiện cập nhật ứng dụng. Ban đầu, số lượng ứng dụng cần cập nhật không nhiều và độ dài chuỗi tham số chỉ khoảng 1000 ký tự nên không gặp vấn đề gì. Tuy nhiên, khi số lượng ứng dụng ngày càng tăng, trong một lần kiểm thử nâng cấp, nhân viên test đã nhập hơn mười nghìn ký tự mô tả cập nhật, dẫn đến lỗi thực thi.

1. Tham khảo tài liệu chính thức từ Microsoft về giới hạn chuỗi dòng lệnh trong Windows Client | Microsoft Learn, có các ghi chú sau:

Các ví dụ sau minh họa cách áp dụng giới hạn này đối với các lệnh chạy trong Command Prompt và các lệnh sử dụng trong file batch.

  • Trong Command Prompt, tổng độ dài của dòng lệnh sau không được vượt quá 8191 ký tự:
    cmd.exe /k ExecutableFile.exe parameter1, parameter2... parameterN
    
  • Trong file batch, tổng độ dài của dòng lệnh sau không được vượt quá 8191 ký tự:
    cmd.exe /k ExecutableFile.exe parameter1, parameter2... parameterN
    
  • Giới hạn này áp dụng cho các dòng lệnh nằm trong file batch khi chạy bằng Command Prompt.
  • Trong Command Prompt, sau khi mở rộng biến môi trường, tổng độ dài của EnvironmentVariable1 chứa EnvironmentVariable2EnvironmentVariable3 không được vượt quá 8191 ký tự:
    c:> set EnvironmentVariable1 = EnvironmentVariable2 EnvironmentVariable3
    
  • Trong file batch, sau khi mở rộng tham số, tổng độ dài của dòng lệnh sau không được vượt quá 8191 ký tự:
    ExecutableFile.exe parameter1 parameter2
    
  • Mặc dù giới hạn Win32 cho biến môi trường là 32.767 ký tự, nhưng Command Prompt sẽ bỏ qua bất kỳ biến môi trường nào kế thừa từ tiến trình cha nếu nó vượt quá giới hạn 8191 ký tự của hệ điều hành. Để biết thêm thông tin về hàm SetEnvironmentVariable, hãy xem hàm SetEnvironmentVariableA.

2. Chuẩn bị: Tạo một chương trình console tên là CmdConsoleApp để gọi khi khởi động tiến trình

// Xem https://aka.ms/new-console-template để biết thêm thông tin
Console.WriteLine("Xin chào, Thế Giới!");

if (args.Length <= 0)
{
    Console.WriteLine($"Không có tham số đầu vào");
    return;
}
Console.WriteLine($"Số lượng tham số đầu vào: {args.Length}");
foreach (var param in args)
{
    Console.WriteLine($"Tham số: {param}");
    Console.WriteLine($"Độ dài tham số: {param.Length}");
}

3. Theo giải thích từ tài liệu chính thức của Microsoft, phương pháp chúng ta sử dụng là khởi động tiến trình con từ tiến trình cha để truyền tham số cho chương trình cập nhật. Giới hạn này do hàm CreateProcess của hệ điều hành quyết định, tức là tổng độ dài không được vượt quá 32.767 ký tự, mã nguồn như sau:

// Xem https://aka.ms/new-console-template để biết thêm thông tin

using System.Diagnostics;
using System.Text;

var executablePath = @$"E:\Code\wutyDemo\CmdConsoleApp\bin\Debug\net8.0\CmdConsoleApp.exe";
var pathLength = executablePath.Length;
StringBuilder builder = new StringBuilder();
var remainingCount = 32767 - pathLength;

builder = new StringBuilder();
for (int i = 0; i < remainingCount; i++)
{
    builder.Append("1");
}

Process.Start(executablePath, builder.ToString());

3.1. Kết quả thực thi như sau, báo lỗi tên file quá dài:

3.2. Nếu giảm bớt số lượng ký tự xuống còn 32763, chương trình chạy bình thường:

4. Tham số dòng lệnh cmd: Theo tài liệu chính thức ở trên, nếu sử dụng cách gọi cmd.exe, tổng độ dài dòng lệnh không được vượt quá 8191 ký tự

// Xem https://aka.ms/new-console-template để biết thêm thông tin

using System.Diagnostics;
using System.Text;

var executablePath = @$"E:\Code\wutyDemo\CmdConsoleApp\bin\Debug\net8.0\CmdConsoleApp.exe";
var pathLength = executablePath.Length;

StringBuilder builder = new StringBuilder();
var commandName = "cmd.exe";
var startupArguments = $"/k {executablePath} ";

var availableParameterCount = 8191 - commandName.Length - startupArguments.Length;
for (int i = 0; i < availableParameterCount; i++)
{
    builder.Append("1");
}
startupArguments += builder.ToString();

using Process executionProcess = new Process();

// Cấu hình thông tin khởi động
executionProcess.StartInfo = new ProcessStartInfo
{
    FileName = commandName,                 // Gọi Command Prompt
    Arguments = startupArguments,   // Tham số thực thi
};
executionProcess.Start();

4.1. Kết quả hiển thị trên console như hình dưới:

4.2. Nếu giảm số lượng ký tự xuống còn 8188, chương trình chạy bình thường:

5. Cách giải quyết giới hạn

Để giải quyết giới hạn này, hãy sử dụng một hoặc nhiều phương pháp sau tùy theo tình huống:

  • Sửa đổi chương trình yêu cầu dòng lệnh dài để chúng sử dụng file chứa thông tin tham số, sau đó đưa tên file vào dòng lệnh. Ví dụ, thay vì sử dụng dòng lệnh ExecutableFile.exe Parameter1 Parameter2... ParameterN trong file batch, hãy sửa đổi chương trình để sử dụng dòng lệnh tương tự như sau, trong đó ParameterFile là file chứa các tham số cần thiết (parameter1 parameter2...ParameterN):
    ExecutableFile.exe c:\temp\ParameterFile.txt
    
  • Sửa đổi chương trình sử dụng biến môi trường lớn để đảm bảo biến môi trường chứa ít hơn 8191 ký tự. Ví dụ, nếu biến môi trường PATH chứa hơn 8191 ký tự, hãy sử dụng một hoặc nhiều phương pháp sau để giảm số ký tự:
    • Sử dụng tên thư mục và tệp ngắn hơn.
    • Giảm độ sâu của cây thư mục.
    • Lưu trữ tệp trong ít thư mục hơn để biến môi trường PATH cần ít thư mục hơn.
    • Tìm hiểu các phương pháp có thể giúp giảm sự phụ thuộc vào PATH để tìm kiếm các file .dll.

Tài liệu tham khảo:

Command Prompt line-string limitation - Windows Client | Microsoft Learn

Thẻ: Windows command-line parameters-limit createprocess cmd-exe

Đăng vào ngày 21 tháng 5 lúc 04:41