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

问题描述 投票:0回答:3

问题:给定文件名和任意字符串列表,是否有规范的方式创建单个命令行,使得Environment.GetCommandLineArgs(和C#的

void main(String[] args)
/ VB的
Sub Main(args() As String)
)将返回相同的字符串列表?


背景:.NET 将命令行拆分为参数的方式出奇地复杂,例如:

如果双引号跟在两个或偶数个反斜杠之后,则每个前面的反斜杠对都将替换为一个反斜杠,并删除双引号。如果双引号后面有奇数个反斜杠,包括一个,前面的每一对都被一个反斜杠替换,剩下的反斜杠被删除;但是,在这种情况下,双引号没有被删除。

许多人尝试简单的“将每个参数放在双引号中并转义现有的双引号”方法,并且一旦其中一个参数包含尾部反斜杠就会失败。关于这个问题,StackOverflow 上有各种问题,例如:

但是,他们的答案要么不够笼统,无法为所有情况提供规范的解决方案,要么似乎是“迭代”开发的(“哦,我忘了还有一个特殊情况,让我们添加它,现在它应该涵盖大多数情况...”)。由于这是一个很常见的问题,我希望看到一个提供信心的解决方案,例如,通过 either

  • 来自权威来源(可能是参与这个疯狂命令行约定的开发人员之一的博客条目)或
  • 提供给定算法满足 .NET 命令行要求的正式证明。
c# .net vb.net command-line-arguments
3个回答
3
投票

这个算法是通用的,来自比较权威的来源(MSDN博客)


1
投票

几年前,Microsoft 宣布他们将在 CodePlex 上发布命令行解析器(而不是本应随 .NET Framework 4 一起提供的 System.Shell.CommandLine)。我不确定他们是否真的这样做了。如果您想要 Microsoft 员工开发的解析器,请查看 cmdline。您也可以在 CodePlex.

中查找命令行解析

你也可以尝试 Mono.Options 这非常强大。


0
投票

从 .NET Core 2.1 开始,不再需要手动转义命令行参数:

ProcessStartInfo
现在有一个
ArgumentList
属性并自动处理任何需要的转义。

引用文档中的例子

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 项目。

© www.soinside.com 2019 - 2024. All rights reserved.