首页 > 解决方案 > 为什么 Dart 将进程参数包装在 C# 没有的引号中?

问题描述

我正在将一些 C# 代码移植到 Windows 上的 Dart 并且浪费了几个小时在 Dart 如何将命令行参数传递给进程的令人沮丧的差异上。

这是被移植的 C# 代码的一部分,它执行得很好:

var startInfo = new ProcessStartInfo("C:\\Program Files\\Inkscape\\inkscape.exe", "--file=\"C:\\Users\\Kent\\test.svg\" --export-png=\"C:\\Users\\Kent\\test.png\" --export-width=100 --export-area-page")
{
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true,
};

var process = Process.Start(startInfo);
process.WaitForExit();

if (process.ExitCode != 0)
{
    var stdout = process.StandardOutput.ReadToEnd();
    var stderr = process.StandardError.ReadToEnd();
    Console.WriteLine(stdout);
    Console.WriteLine(stderr);
}

正确运行它会生成一个输出 PNG 文件。但是,Dart 等价物不会:

final inkscapeResult = await Process.run(
  r'C:\Program Files\Inkscape\inkscape.exe',
  [
    '--file="C:\\Users\\Kent\\test.svg"',
    '--export-png="C:\\Users\\Kent\\test.png"',
    '--export-width=100',
    '--export-area-page',
  ],
);
final exitCode = inkscapeResult.exitCode;

if (exitCode != 0) {
  writeError(inkscapeResult.stdout);
  writeError(inkscapeResult.stderr);
}

相反,该过程以代码退出,1程序输出:

** (inkscape.exe:5604): WARNING **: 17:30:09.785: Can't open file: "C:\Users\Kent\test.svg" (doesn't exist)

** (inkscape.exe:5604): WARNING **: 17:30:09.785: Can't open file: "C:\Users\Kent\test.svg" (doesn't exist)

** (inkscape.exe:5604): WARNING **: 17:30:09.785: Specified document "C:\Users\Kent\test.svg" cannot be opened (does not exist or not a valid SVG file)

众所周知,Inkscape 在命令行上执行时有点挑剔,但我读过的建议是简单地传递完整路径,我正在这样做。

我发现如果我避免争论,它会起作用:

final inkscapeResult = await Process.run(
  r'C:\Program Files\Inkscape\inkscape.exe --file="C:\\Users\\Kent\\test.svg" --export-png="C:\\Users\\Kent\\test.png" --export-width=100 --export-area-page',
  [],
);

所以我推断 Dart 一定是在做一些 Inkscape 不喜欢的论点。我设法使用 Process Explorer 捕捉到它,它具有以下命令行:

"C:\Program Files\Inkscape\inkscape.exe" "--file=\"C:\Users\Kent\test.svg\"" "--export-png=\"C:\Users\Kent\test.png\"" --export-width=100 --export-area-page

如果我直接从命令行运行它,我不会得到任何输出,但图像也不会生成,所以大概它以同样的方式失败了。将此与 C# 代码生成的命令行进行比较:

"C:\Program Files\Inkscape\inkscape.exe" --file="C:\Users\Kent\test.svg" --export-png="C:\Users\Kent\test.png" --export-width=100 --export-area-page

Dart 用引号将每个单独的参数包装起来,而 C# 不是(尽管 C# 的 API 甚至不分隔单独的参数)。这以某种方式破坏了 Inkscape 的解析器。

谁在这里错了?我、Dart、C# 还是 Inkscape?

标签: c#windowsdartcommand-line

解决方案


我认为最简单的方法是像这样拆分参数名称和参数值:

  final inkscapeResult = await Process.run(r'C:\Program Files\Inkscape\inkscape.exe', [
    '--file', 'C:\\Users\\Kent\\test.svg',
    '--export-png', 'C:\\Users\\Kent\\test.png',
    '--export-width', '100',
    '--export-area-page',
  ]);

这样您就不必担心转义或引用参数。


推荐阅读