为什么 PowerShell 参数有两对引号?

Why are there two pairs of quotes for PowerShell arguments?

提问人:t3chb0t 提问时间:6/6/2023 最后编辑:t3chb0t 更新时间:6/10/2023 访问量:87

问:

我正在构建一个需要通过 C# 定期执行 PowerShell 脚本(等)的 Windows 服务,我在这里找到了关于如何执行此操作的答案,但那里的示例使用了两对引号(首先是双引号,然后是单引号),这非常令人困惑:*.ps1 -Option ValueProcess"'Arguments

process.StartInfo.Arguments = "\"&'"+strCmdText+"'\"";

它们真的有必要吗,如果是,那为什么?

C# PowerShell 窗口 引号

评论

1赞 Charlieface 6/6/2023
您可以直接从 C# 执行 Powershell,而不必外出 stackoverflow.com/questions/527513/...powershell.exe
0赞 t3chb0t 6/7/2023
@Charlieface我知道,谢谢:)不幸的是,启动器(Windows 服务)无法快速更新,因此我现在必须以经典方式处理它。
1赞 mklement0 6/11/2023
@t3chb0t,慷慨的赏金奖励非常受欢迎。
1赞 t3chb0t 6/11/2023
@mklement0这么简单的一句话问题有很多细节,但现在我觉得我一点一点地知道我在那里实际在做什么,而不仅仅是复制/粘贴东西;-]

答:

1赞 openshac 6/6/2023 #1

在大多数情况下,通过 C# 执行 PowerShell 脚本时,不需要在属性中使用多对引号。您提供的代码片段似乎过于复杂或包含不必要的引号。ArgumentsProcess

通常,在 C# 中设置 PowerShell 脚本的属性时,通常只需提供脚本文件本身的路径。例如:Arguments

process.StartInfo.Arguments = "path/to/script.ps1";

这假定你已将对象的属性设置为 PowerShell 可执行文件的路径(或取决于你的系统)。FileNameProcessStartInfopowershell.exepwsh.exe

但是,在某些情况下,可能需要传递其他参数或处理脚本路径中的空格或特殊字符。在这种情况下,您可能需要将路径括在双引号中。例如:

process.StartInfo.Arguments = "\"path/to/script with spaces.ps1\"";

在这种情况下,双引号用于确保将整个路径视为单个参数。

根据您提供的代码片段 (),您似乎正在尝试将命令或脚本文本作为参数而不是脚本文件路径传递。但是,该代码段中双引号和单引号的具体用法似乎是不必要的,并且可能导致语法错误。\"&'"+strCmdText+"'\"

为了提供更准确的答案,如果您能提供执行 PowerShell 脚本的上下文或特定要求,以便我进一步为您提供帮助,那将会很有帮助。

评论

0赞 t3chb0t 6/6/2023
哦,我明白了!我还在设置中添加了更多细节。它是一种定期运行脚本的 Windows 服务。*.ps1
1赞 mklement0 6/8/2023 #2

若要提供更侧重于 PowerShell 的答案,请执行以下操作:

那里的示例使用两对引号(首先是双引号,然后是单引号)作为参数 (...)它们真的有必要吗,如果是,那为什么?"'

  • 引用要求取决于是否使用 PowerShell CLI 的 或参数(Powershell.exe 用于 Windows PowerShell,pwsh 用于 PowerShell (Core) 7+)。-File-Command

    • 在缺少任何一个参数的情况下,假设 ,假设 。powershell.exe-Commandpwsh.exe-File

    • -Command允许传递任意 PowerShell 命令,代码可以选择分布在多个参数中。

      • 在初始命令行分析期间,未转义的字符将被剥离,但字符将按原样传递。"'
      • 保留为要执行的 PowerShell 代码的一部分需要将其转义为 (原文如此;即使必须使用 PowerShell-internally) 也是如此。"\"`"
    • -File期望脚本文件 () 的路径执行,任何其他参数都作为文本值传递给该脚本。*.ps1

      • 只有引号可以与句法功能一起使用 - 任何字符都可以逐字使用。"'
  • 从根本上说,当脚本文件路径包含元字符(尤其是空格)时,它只需要引用。-File-Command

  • 需要引用时,方法因以下因素而异:-Command-File

  • -File:

    • 在文件路径周围使用嵌入引号(以及任何需要引号的传递参数) - 为了嵌入到 C# 逐字字符串中而转义:"..."""...""

      var scriptPath = @"C:\path with spaces\script.ps1";
      process.StartInfo.Arguments = $@"-File ""{scriptPath}""";
      
  • -Command:

    • 虽然可以使用嵌入引用,如问题中所示,但这样做并不完全健壮,除非采取额外的操作:是文件名中的合法字符,因此包含的路径会破坏命令(这可以通过额外的努力来避免;请参阅下面的边缘情况)。'...'''

    • 使用嵌入式引号可以避免此问题,因为这在文件名中是无效的(至少在 Windows 上是这样)。由于上述原因,这需要 -eoffing 字符(为可读性添加空格):"...""\"

       var scriptPath = @"C:\path with spaces\script.ps1";
       process.StartInfo.Arguments = $@" -Command "" & \""{scriptPath}\"" "" ";
      
    • 注意:

      • 如果执行的唯一操作是调用带有文字参数的脚本,则没有理由改用 - use。-Command-File

      • 这是 PowerShell 中的一项基本语法要求(不适用于 ),必须通过调用运算符调用带引号的命令。-File&

      • 要执行的代码作为单个参数传递,包含在 中。在不涉及 shell 的调用中,这并不是绝对必要的,但可以避免因 PowerShell 将多个参数“拼接”回一起以形成要执行的代码而导致的空格规范化"..."-Command

      • 有一个 - 主要是假设的 - 边缘情况(这不会影响参数):如果你的文件路径包含逐字标记,例如 ,它们将受到 PowerShell 的 - 不需要的 - 字符串插值;在这种情况下,必须改用嵌入式引号,但要使用任何嵌入的字符。 转义为:-File$foo'...''''

        var scriptPath = @"C:\path with spaces\script.ps1";
        process.StartInfo.Arguments = $@" -Command "" & '{scriptPath.Replace("'", "''")}' "" ";