如何将参数数组序列化为 .NET Standard 2.0 中可用的 ProcessStartInfo 字符串?

How to serialize arguments array into a string for ProcessStartInfo available in .NET Standard 2.0?

.NET 5.0 中有 ProcessStartInfoArgumentsList 属性,但是当我将我的库定位到 .NET Standard 2.0 时,我没有它可用,所以我必须手动转换参数。

显然,参数可以包含空格,并且它们也由空格分隔。所以我想我应该使用引号,然后引用可能出现在参数中的引号,这可能都是特定于平台的。

.NET Standard 2.0 中是否有可访问的工具? 如果不是,我的转换究竟应该做什么?

我知道它应该在包含空格的参数上添加双引号。 它还应该用双引号转义双引号。 我通过在 Visual Studio:

的项目属性的调试面板中尝试以下命令行来解决这个问题
arg1 "arg 2" "arg ""3"""

当应用程序启动时,主函数获取以下参数:

“arg1”、“arg 2”和“arg“3””。所以看起来应该可行,但我不完全确定是否应该考虑这些。

我也想知道 - 它会在 Linux 上运行吗? Linux 的转换是以相同方式还是以不同方式完成的?

更新: 我检查了 .NET 源...和...

https://github.com/dotnet/runtime/blob/6d707d78c87c6c619d48537dff0568696a5d65bd/src/libraries/System.Private.CoreLib/src/System/PasteArguments.Unix.cs#L9

https://github.com/dotnet/runtime/blob/6d707d78c87c6c619d48537dff0568696a5d65bd/src/libraries/System.Private.CoreLib/src/System/PasteArguments.Windows.cs#L9

https://github.com/dotnet/runtime/blob/6d707d78c87c6c619d48537dff0568696a5d65bd/src/libraries/System.Private.CoreLib/src/System/PasteArguments.cs#L10

我看到的唯一区别是“无法通过解析器获取文字引用。” - 作为 Windows 的规则,引号在 Unix 版本上通常用双引号解析。这是我在 Windows.

上测试我的 Visual Studio 时发现的命令行结果

因为我只需要为 ProcessStartInfo 创建命令行而不是将它们解析为参数集合 - 如果我采用前面提到的引用规则是非常安全的 - 所以将任何双引号转换为双双引号并添加双引号引号包含空格的所有参数。它应该适用于两个系统,并且可能会在一些非常非常具体的情况下失败,而这些情况无论如何在我的库和用例中都是不可能的。我的库是命令行工具的 class 包装器,顺便说一句,命令行工具 AFAIK 仅存在于 Windows.

但是,class 旨在可能存在于 Linux 版本中,但它的 IsSupported 属性 returns 在 [=55 上是错误的=].因此,无论 lib 做什么,都应该由 Linux 平台上的另一个工具处理。目标是在一个程序中允许不同的实现,具体取决于 OS 它是 运行。

public static class ProcessExtensions {

    public static void SetArguments(this ProcessStartInfo processStartInfo, IEnumerable<string> args) {
        processStartInfo.Arguments = String.Join(" ", args.Select(arg => {
            if (arg.Contains('"')) arg = arg.Replace("\"", "\"\"");
            if (arg.Contains(' ')) arg = '"' + arg + '"';
            return arg;
        }));
    }
}

这是我的快速解决方案,但也许您可以想出更好的办法。我知道,args 没有经过空测试。然而,该项目被标记为 nullable,因此 IEnumerable<string> 而不是 IEnumerable<string?>? 意味着 args 不能为 null,VS 会将所有可能的 null 参数标记为警告。

我从答案 开始,但当参数确实包含单引号 (') 时,它在 Linux 系统上对我不起作用。在所有情况下对我有用的是

public static string MakeArguments(IEnumerable<string> args)
{
    return String.Join(" ", args.Select(arg =>
    {
        if (arg.Contains('\'')) arg = arg.Replace("'", "'\"'\"'");
        arg = '\'' + arg + '\'';
        return arg;
    }));
}

请注意,有意 每个 参数都用单引号括起来,以免错过对需要转义的字符的测试。另请注意,序列 '"'"' 被解释为用单引号括起来的字符串中的 '