这个参数在c#中是如何传递的?

本文关键字:何传递 参数 | 更新日期: 2023-09-27 17:49:59

我看过这段代码,但不太明白为什么它能成功运行。

class Program
{
    public static void Main()
    {
        var startInfo = new ProcessStartInfo
        {
            FileName = "PowerShell.exe",
            Arguments = @"-NoLogo -NoProfile ""Get-Content Queries.txt"" | Set-Content Output.tsv"
        };
        Console.WriteLine(startInfo.Arguments);
        Process.Start(startInfo);
    }
}

如果我尝试在命令提示符中直接执行powershell -NoLogo -NoProfile "Get-Content Queries.txt" | Set-Content Output.tsv,它会抛出错误消息,但上面的代码片段可以成功完成。

代码中的双引号是如何处理的?

这个参数在c#中是如何传递的?

你说的命令提示符是指cmd.exe吗?如果是这样,您正在处理cmd.exe的解析,它不能很好地处理|,例如:

C:'>dir | foo.txt
'foo.txt' is not recognized as an internal or external command,
operable program or batch file.

如果我在PowerShell V4提示符中尝试您的命令,它可以正常工作。此外,在c#中执行的脚本使用PowerShell的命令行解析,而不是cmd.exe的解析。

命令行参数使用空格作为分隔符进行解析,这当然可能是一个问题,例如具有空格的路径,例如Get-Content Queries.txt。因此,为了解决这个问题,任何用双引号括起来的参数都将避免这种以空格分隔符进行解析。

那么为什么双引号可以工作呢?

对于所讨论的代码,因为字符串以@字符串文字为前缀,所以允许不转义的双引号。关于@字符串文字修饰符如何工作的一个很好的简短帖子(由Jon Skeet撰写)可以在字符串文字开始之前的@是什么意思?引用其中的一句话:

它的基本意思是,"在到达下一个引号字符之前,不要对字符进行任何解释"。因此,一个完整的字符串字面值可以包含反斜杠(不需要将它们加倍),甚至可以包含行分隔符。要在逐字文本中获得双引号("),您只需将其双引号括起来…

但是手动复制到命令行不工作,有什么不同?

因此,当将其复制到命令行时,这将不会以完全相同的方式工作,因为它不包括Process.Start()在将参数包装在(等待它…)另一个引号中所采取的额外步骤!如PowerShell和命令行上的双引号所述:

下面是一些使其正常工作的方法:

  • 使用单引号:

    powershell.exe C:'Scripts'ParamCheck.ps1 -Something 'one two'

  • 使用反斜杠分隔符(即使PowerShell内部使用left-single-quote"):

    powershell.exe C:'Scripts'ParamCheck.ps1 -Something '"one two'"

  • 使用三个双引号:

    powershell.exe C:'Scripts'ParamCheck.ps1 -Something """one two"""

引用:

  • 字符串字面值开始前的@是什么意思?
  • PowerShell和命令行的双引号
  • 什么时候我必须把双引号在参数值周围?