这个论点是如何在C#中传递的?

时间:2014-03-12 22:02:48

标签: c# .net powershell

我已经看过这段代码片段,但无法弄清楚为什么它可以成功运行。

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,它会抛出错误消息,但上面的代码片段可能会成功完成。

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

2 个答案:

答案 0 :(得分:1)

当你说命令提示符时,你的意思是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的解析。

答案 1 :(得分:0)

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

为什么双引号有效?

使用相关代码,因为字符串以@字符串文字为前缀,所以允许双引号而不转义。关于@字符串文字修饰符如何工作(由Jon Skeet不少)的简短帖子可以在What does an @ before the start of a string literal mean?找到。引用一句话:

  

它基本上意味着,“#”不会对字符应用任何解释,直到达到下一个引号字符为止#34;。因此,逐字字符串文字可以包含反斜杠(没有它们被加倍)甚至行分隔符。要在逐字逐句中获得双引号("),您需要加倍...

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

因此,当将其复制到命令行时,这不会以完全相同的方式工作,因为它不包含Process.Start()包装参数所需的额外步骤(等待对它...)另一个引用!如PowerShell and double quotes on the command line

中所述
  

以下是使这项工作正常运行的一些方法:

     
      
  • 使用单引号:

         

    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"""

  •   

<强>参考文献: