【问题标题】:Why does Dart wrap process arguments in quotes where C# does not?为什么 Dart 将进程参数包装在 C# 没有的引号中?
【发布时间】:2019-09-10 07:43:31
【问题描述】:

我正在将一些 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?

【问题讨论】:

  • 似乎只有当命令行参数本身包含双引号时,Dart 才会添加周围的双引号。例如:'--file=C:\\Users\\Kent\\test.svg'.

标签: c# windows dart command-line


【解决方案1】:

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

  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',
  ]);

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

【讨论】:

  • 这不会给出正确的命令行,它缺少 = 一开始。
  • 它似乎工作。通常,程序会接受两种指定参数的方式。
  • 虽然这在这种情况下有效(谢谢,请投赞成票),但我认为它不是一个非常令人满意的答案。 Inkscape 接受这两种形式似乎有点巧合,当然它的文档鼓励使用= 的第一种形式。
  • 我写了很多 dart 脚本来与其他程序(imagemagick、sox、ffmpeg、fontforge...)进行交互,我从未见过不能使用“空格分隔”的脚本形式。
猜你喜欢
  • 2013-11-05
  • 2020-02-04
  • 1970-01-01
  • 2018-08-05
  • 1970-01-01
  • 2022-01-09
  • 2021-05-04
  • 2019-03-28
  • 1970-01-01
相关资源
最近更新 更多