转义.NET命令行参数的规范解决方案

ljsrvy3e  于 2023-03-24  发布在  .NET
关注(0)|答案(3)|浏览(111)

问题:给定一个文件名和一个任意的字符串列表,是否有一种 * 规范的方式 * 来创建一个命令行,使Environment.GetCommandLineArgs(以及C#的void main(String[] args)/ VB的Sub Main(args() As String))返回相同的字符串列表?
背景:.NET将命令行拆分为参数的方式是surprisingly complex,例如:

如果双引号跟在两个或偶数个反斜杠之后,则前面的每对反斜杠都将被一个反斜杠替换,并删除双引号。如果双引号跟在奇数个反斜杠之后,其中只有一个反斜杠,则前面的每对反斜杠都将被一个反斜杠替换,并删除剩余的反斜杠;但是,在这种情况下,双引号不会被删除。
许多人尝试简单的“将每个参数放在双引号中并转义现有的双引号”方法,并且一旦其中一个参数包含尾随反斜杠就会失败。关于这个问题,StackOverflow上有各种各样的问题,例如:

然而,他们的答案要么不够通用,无法为所有情况提供规范的解决方案,要么似乎是“迭代”开发的(“哦,还有一个特殊情况我忘了,让我们添加它,现在它应该涵盖大多数情况......”)。

  • 来自权威来源(可能是参与这个疯狂的命令行约定的开发人员之一的博客条目)或
  • 提供给定算法满足.NET命令行要求的正式证明。
ltskdhd1

ltskdhd11#

This algorithm是通用的,来自相对权威的来源(MSDN博客)。

v2g6jxz6

v2g6jxz62#

几年前,微软宣布他们将在CodePlex上发布一个命令行解析器(而不是.NET Framework 4附带的System.Shell.CommandLine)。我不确定他们是否真的这么做了。如果你想让微软员工开发一个解析器,可以看看cmdline。你也可以在CodePlex中查找命令行解析器。
你也可以试试Mono.Options,它非常强大。

a64a0gku

a64a0gku3#

从.NET Core 2.1开始,不再需要手动转义命令行参数:ProcessStartInfo现在有一个ArgumentList属性,并自动处理任何需要的转义。
引用the documentation的例子:

var info = new System.Diagnostics.ProcessStartInfo("cmd.exe");
info.ArgumentList.Add("/c");
info.ArgumentList.Add("dir");
info.ArgumentList.Add(@"C:\Program Files\dotnet");

在这里你可以看到算法的全部荣耀(包括著名的“2n+1反斜杠规则”)。它是MIT许可的,这使得它很容易在需要的时候反向移植到.NET Framework 4.8项目。

相关问题