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

这个参数是如何在C#中传递的?,c#,.net,powershell,C#,.net,Powershell,我已经看过这段代码片段,但不太明白为什么它可以成功运行 class Program { public static void Main() { var startInfo = new ProcessStartInfo { FileName = "PowerShell.exe", Arguments = @"-NoLogo -NoProfile ""Get-Content Queries.txt"" |

我已经看过这段代码片段,但不太明白为什么它可以成功运行

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 querys.txt”| Set Content Output.tsv
,它将抛出错误消息,但上述代码片段可以成功完成


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

命令行参数是使用空格作为分隔符来解析的,这当然可能是有空格的路径之类的问题,例如
Get Content querys.txt
。所以为了避免这种情况,任何用双引号括起来的参数都可以避免使用空格分隔符进行这种类型的解析

为什么双引号有效?

对于所讨论的代码,由于字符串的前缀是
@
字符串文字,因此允许使用双引号而不转义。一篇关于
@
字符串文字修饰符如何工作的短文(作者Jon Skeet)可以在上找到。引用这句话:

它的基本意思是,“在到达下一个引号字符之前,不要对字符应用任何解释”。因此,一个逐字字符串文字可以包含反斜杠(不需要将它们折叠起来),甚至可以包含行分隔符。要在逐字逐句中获得双引号(“),只需将其加倍

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

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

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

  • 使用单引号:

    powershell.exe C:\Scripts\ParamCheck.ps1-一些“一两”字

  • 使用 反斜杠分隔符(即使PowerShell在内部使用 左单引号`):

    powershell.exe C:\Scripts\ParamCheck.ps1-一些东西\“一两\

  • 使用 三个双引号:

    powershell.exe C:\Scripts\ParamCheck.ps1-某物“一两”

参考文献:


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

尝试提供查询的完整路径。txt@cheedep执行“设置内容”时收到的错误消息未被识别为内部或外部命令,p程序或批处理文件。因此,我认为它与命令参数解析有关,而不是与输入文件的相对位置有关。与您在C#中在命令行上执行的操作等效的是
powershell“-NoLogo-NoProfile”“Get Content querys.txt”“| Set Content Output.tsv
@PrestonGuillot这会抛出一条错误消息,如:字符串缺少终止符:“.+CategoryInfo:ParserError:(:)[],ParentContainesErrorRecordException+FullyQualifiedErrorId:TerminatorExpectedAtendofString如果您只想在命令提示符下执行,则需要使用powershell-NoLogo-NoProfile”Get Content querys.txt | Set Content Output.tsv“为什么它要用C#没有引号,我不知道。谢谢。但是为什么C代码能够成功执行呢?更新了答案。这是因为
@
文字。谢谢你的详细解释,马特。让我试着把我的问题表述得更清楚一点。我理解逐字逐句的字面意思,以及C#中如何解释这个参数。因此,如果我理解正确,PowerShell.exe的参数应该是-NoLogo-NoProfile“Get Content querys.txt”| Set Content Output.tsvb,但如果我直接将该命令抛出命令提示符,它将不会执行。这是为什么?正如进一步参考中的第一项所示(
PowerShell和命令行上的双引号)
),可以使用单引号甚至三引号将其转换为命令行。我会更新答案。