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

huangapple go评论58阅读模式
英文:

Why are there two pairs of quotes for PowerShell arguments?

问题

我正在构建一个需要定期执行PowerShell脚本(*.ps1 -Option Value等)的Windows服务,通过C#的Process执行,并在这里找到了如何实现的答案。但是,该答案中的示例在Arguments参数中使用了两对引号(首先是双引号",然后是单引号'),这令人感到困惑:

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

它们是否都是必需的?如果是,为什么?

英文:

I was building a Windows Service that needs to periodically execute PowerShell scripts (*.ps1 -Option Value etc) via C#'s Process and I found this answer here about how to do this, but the example there uses two pairs of quotes (first double " then single ') for the Arguments which is quite confusing:

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

Are they both really necessary and if yes then why?

答案1

得分: 1

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

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

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

这假定你已经设置了ProcessStartInfo对象的FileName属性为PowerShell可执行文件的路径(根据你的系统是powershell.exe还是pwsh.exe)。

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

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

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

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

为了提供更准确的答案,如果你能提供执行PowerShell脚本的上下文或具体要求,将会更有帮助,这样我可以进一步协助你。

英文:

The use of multiple pairs of quotes in the Arguments property when executing a PowerShell script via C#'s Process is not necessary in most cases. It seems like the code snippet you provided might be overly complex or contain unnecessary quotes.

In general, when setting the Arguments property for a PowerShell script in C#, you typically only need to provide the path to the script file itself. For example:

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

This assumes that you have set the FileName property of the ProcessStartInfo object to the path of the PowerShell executable (powershell.exe or pwsh.exe depending on your system).

However, there might be certain cases where you need to pass additional arguments or deal with spaces or special characters in the script path. In such situations, you may need to enclose the path in double quotes. For example:

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

In this case, the double quotes are used to ensure that the entire path is treated as a single argument.

Based on the code snippet you provided (\"&'"+strCmdText+"'\"), it seems like you are trying to pass a command or script text as an argument rather than a script file path. However, the specific usage of double and single quotes in that snippet appears to be unnecessary and could potentially lead to syntax errors.

To provide a more accurate answer, it would be helpful if you could provide the context or specific requirements for executing the PowerShell script so that I can assist you further.

答案2

得分: 1

为了提供一个更加专注于PowerShell的答案:

  • 该示例中使用了两对引号(首先是双引号",然后是单引号')来包裹参数(...)。它们是否都是必需的,如果是,为什么?
  • 引号的需求取决于PowerShell CLI的-File-Command参数的使用情况(对于Windows PowerShell的powershell.exe,对于PowerShell(Core)7+的pwsh)。

    • 如果没有指定这两个参数中的任何一个,powershell.exe将假定-Command,而pwsh.exe将假定-File

    • -Command允许您传递任意的PowerShell命令,代码可以选择跨多个参数进行传递。

      • 未转义"字符会在初始命令行解析期间被删除,但'字符会原样传递。
      • 如果要保留"作为要执行的PowerShell代码的一部分,需要将它们转义为\"(即使在PowerShell内部必须使用`")。
    • -File期望执行一个脚本文件的路径(*.ps1),任何附加的参数都将作为字面值传递给该脚本。

      • 只能使用"引用与语法相关的函数 - 任何'字符都将原样使用。
  • 从根本上说,在-File-Command的情况下,只有当脚本文件路径包含元字符(特别是空格)时,才需要引用。

  • 当引用是必需时,取决于-Command-File的不同:

    • -File

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

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

      • 尽管可以使用嵌套的'...'引号,如问题中所示,但这样做并不是完全健壮的,除非采取额外的措施:'是文件名中的合法字符,因此包含'的路径将中断命令(可以通过额外的工作来避免,参见下面的边缘案例)。

      • 使用嵌套的"..."引号可以避免此问题,因为"在文件名中不是有效的(至少在Windows上不是)。基于上述原因,这需要对"字符进行\转义(为了可读性添加了空格):

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

        • 如果您执行的唯一操作是调用带有字面值参数的脚本,则没有理由使用-Command - 而应使用-File

        • 在PowerShell中,这是一个基本的语法要求(不适用于-File):*引用的命令必须通过&,也就是调用运算符来调用。

        • 要执行的代码作为单个参数传递,用"..."括起来传递给-Command。在不涉及shell的情况下,这并不是严格必需的,但它可以避免空格规范化,这将导致PowerShell将多个参数拼接在一起以形成要执行的代码。

        • 有一个 - 大部分是假设的 - 边缘情况(不影响-File参数):如果您的文件路径包含了像$foo这样的原始令牌,它们将被PowerShell 不希望的字符串插值;在这种情况下,必须使用嵌套的'...'引号,但必须对任何嵌入的'字符进行转义为''

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

英文:

To offer a more PowerShell-focused answer:

> the example there uses two pairs of quotes (first double " then single ') for the Arguments (...) Are they both really necessary and if yes then why?

  • The quoting requirements depend on whether the -File or the -Command parameter of the PowerShell CLI (powershell.exe for Windows PowerShell, pwsh for PowerShell (Core) 7+) is used.

    • In the absence of either parameter, powershell.exe assumes -Command, pwsh.exe assumes -File.

    • -Command allows you to pass arbitrary PowerShell commands, with the code optionally spread across multiple arguments.

      • Unescaped " characters are stripped during the initial command-line parsing, but ' characters are passed through as-is.
      • Preserving " as part of the PowerShell code to execute require escaping them as \" (sic; even though PowerShell-internally `" must be used).
    • -File expects the path of a script file (*.ps1) to execute, with any additional arguments being passed as literal values to that script.

      • Only " quoting can be used with syntactic function - any ' characters are used verbatim.
  • Fundamentally - with both -File and -Command - a script-file path only needs quoting if it contains metacharacters, notably spaces.

  • When quoting is needed, the approaches differ depending on -Command vs. -File:

  • -File:

    • Use embedded "..." quoting around the file path (and around any pass-through arguments that need quoting) - escaped as ""..."" for the sake of embedding in the C# verbatim string:

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

    • While embedded '...' quoting, as in the question, could be used, doing so isn't fully robust, unless extra action is taken: ' is a legal character in file names, so a path containing ' would break the command (which could be avoided with extra effort; see the edge case below).

    • Using embedded "..." quoting avoids this problem, given that " isn't valid in file names (at least on Windows). For the reasons stated above, this requires \-escaping the " characters (spaces added for readability):

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

      • If the only operation you're performing is calling a script with literal arguments, there is no reason to use -Command - use -File instead.

      • It is a fundamental syntax requirement in PowerShell (which does't apply to -File) that a quoted command must be called via &, the call operator.

      • The code to execute is passed as a single argument, enclosed in "..." to -Command. This isn't strictly necessary in an invocation that doesn't involve a shell, but avoids whitespace normalization that would result from PowerShell "stitching" multiple arguments back together to form the code to execute.

      • There's a - largely hypothetical - edge case (which does not affect the -File parameter): If you had file paths that contain verbatim tokens such as $foo, they would be subject to - unwanted - string interpolation by PowerShell; in that case, embedded '...' quoting must be used instead, but with any embedded ' chars. escaped as '':

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

huangapple
  • 本文由 发表于 2023年6月6日 16:46:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76412895.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定