简体   繁体   English

PowerShell 从命令行中去除双引号 arguments

[英]PowerShell stripping double quotes from command line arguments

Recently I have been having some trouble using GnuWin32 from PowerShell whenever double quotes are involved.最近,每当涉及双引号时,我在使用 PowerShell 中的 GnuWin32 时遇到了一些麻烦。

Upon further investigation, it appears PowerShell is stripping double quotes from command line arguments, even when properly escaped.经过进一步调查,PowerShell 似乎正在从命令行 arguments 中删除双引号,即使正确转义也是如此。

PS C:\Documents and Settings\Nick> echo '"hello"'
"hello"
PS C:\Documents and Settings\Nick> echo.exe '"hello"'
hello
PS C:\Documents and Settings\Nick> echo.exe '\"hello\"'
"hello"

Notice that the double quotes are there when passed to PowerShell's echo cmdlet, but when passed as an argument to echo.exe , the double quotes are stripped unless escaped with a backslash (even though PowerShell's escape character is a backtick, not a backslash).请注意,双引号在传递给 PowerShell 的echo cmdlet 时存在,但当作为参数传递给echo.exe时,双引号将被删除,除非使用反斜杠进行转义(即使 PowerShell 的转义字符是反斜杠,而不是反斜杠)。

This seems like a bug to me.这对我来说似乎是一个错误。 If I am passing the correct escaped strings to PowerShell, then PowerShell should take care of whatever escaping may be necessary for however it invokes the command.如果我将正确的转义字符串传递给 PowerShell,那么 PowerShell 应该处理 escaping 可能需要的任何东西,但它会调用命令。

What is going on here?这里发生了什么?

For now, the fix is to escape command line arguments in accordance with these rules (which seem to be used (indirectly) by the CreateProcess API call which PowerShell uses to invoke.exe files):目前,修复是根据这些规则转义命令行 arguments (这似乎由CreateProcess API 调用(PowerShell 用于调用.exe 文件)使用(间接):

  • To pass a double quote, escape with a backslash: \" -> "要传递双引号,请使用反斜杠转义: \" -> "
  • To pass a one or more backslashes followed by a double quote, escape each backslash with another backslash and escape the quote: \\\\\" -> \\"要传递一个或多个反斜杠后跟双引号,请使用另一个反斜杠转义每个反斜杠并转义引号: \\\\\" -> \\"
  • If not followed by a double quote, no escaping is necessary for backslashes: \\ -> \\如果后面没有双引号,则反斜杠不需要 escaping: \\ -> \\

Note that further escaping of double quotes may be necessary to escape the double quotes in the Windows API escaped string to PowerShell.请注意,可能需要进一步的双引号 escaping 以将 Windows API 转义字符串中的双引号转义为 Z3D265B4E801EEEF18DCCDF173。

Here are some examples, with echo.exe from GnuWin32:下面是一些例子,来自 GnuWin32 的echo.exe

PS C:\Documents and Settings\Nick> echo.exe "\`""
"
PS C:\Documents and Settings\Nick> echo.exe "\\\\\`""
\\"
PS C:\Documents and Settings\Nick> echo.exe "\\"
\\

I imagine that this can quickly become hell if you need to pass a complicated command line parameter.我想如果你需要传递一个复杂的命令行参数,这很快就会变成地狱。 Of course, none of this documented in the CreateProcess() or PowerShell documentation.当然,这些都没有记录在CreateProcess()或 PowerShell 文档中。

Also note that this is not necessary to pass arguments with double quotes to .NET functions or PowerShell cmdlets.另请注意,不必将带有双引号的 arguments 传递给 .NET 函数或 PowerShell cmdlet。 For that, you need only escape your double quotes to PowerShell.为此,您只需将双引号转义为 PowerShell。

Edit: As Martin pointed out in his excellent answer, this is documented in the CommandLineToArgv() function (which the CRT uses to parse the command line arguments) documentation.编辑:正如马丁在他出色的回答中指出的那样,这记录在CommandLineToArgv() function (CRT 用于解析命令行参数)文档中。

It is a known thing :这是一个已知的事情

It's FAR TOO HARD to pass parameters to applications which require quoted strings.将参数传递给需要引用字符串的应用程序太难了。 I asked this question in IRC with a "roomful" of PowerShell experts, and it took hour for someone to figure out a way (I originally started to post here that it is simply not possible).我在 IRC 中与“满屋”的 PowerShell 专家一起问了这个问题,有人花了一个小时才想出办法(我最初开始在这里发帖说这根本不可能)。 This completely breaks PowerShell's ability to serve as a general purpose shell, because we can't do simple things like executing sqlcmd.这完全破坏了 PowerShell 作为通用 shell 的能力,因为我们不能做像执行 sqlcmd 这样简单的事情。 The number one job of a command shell should be running command-line applications... As an example, trying to use SqlCmd from SQL Server 2008, there is a -v parameter which takes a series of name:value parameters.命令 shell 的首要任务应该是运行命令行应用程序...例如,尝试使用 SQL Server 2008 中的 SqlCmd,有一个 -v 参数,它采用一系列名称:值参数。 If the value has spaces in it, you must quote it...如果值中有空格,则必须引用它...

...there is no single way to write a command line to invoke this application correctly, so even after you master all 4 or 5 different ways of quoting and escaping things, you're still guessing as to which will work when... or, you can just shell out to cmd, and be done with it. ...没有一种方法可以编写命令行来正确调用此应用程序,因此即使您掌握了所有 4 或 5 种不同的引用方式和 escaping 的东西,您仍然在猜测什么时候会起作用......或者,您可以将 shell 输出到 cmd,然后完成。

TL;DR TL;博士

If you just want a solution for Powershell 5, see:如果您只需要 Powershell 5 的解决方案,请参阅:

ConvertTo-ArgvQuoteForPoSh.ps : Powershell V5 (and C# Code) to allow escaping native command arguments ConvertTo-ArgvQuoteForPoSh.ps : Powershell V5(和 C# 代码)以允许 escaping 本机命令 ZDBC11CAABD8BDA2777776

The Question I will try to answer我将尝试回答的问题

..., it appears PowerShell is stripping double quotes from command line arguments, even when properly escaped. ...,似乎 PowerShell 正在从命令行 arguments 中删除双引号,即使正确转义也是如此。

 PS C:\Documents and Settings\Nick> echo.exe '"hello"' hello PS C:\Documents and Settings\Nick> echo.exe '\"hello\"' "hello"

Notice that the double quotes are there when passed to PowerShell's echo cmdlet, but when passed as an argument to echo.exe, the double quotes are stripped unless escaped with a backslash (even though PowerShell's escape character is a backtick, not a backslash).请注意,双引号在传递给 PowerShell 的 echo cmdlet 时存在,但当作为参数传递给 echo.exe 时,双引号将被去除,除非使用反斜杠进行转义(即使 PowerShell 的转义字符是反斜杠,而不是反斜杠)。

This seems like a bug to me.这对我来说似乎是一个错误。 If I am passing the correct escaped strings to PowerShell, then PowerShell should take care of whatever escaping may be necessary for however it invokes the command.如果我将正确的转义字符串传递给 PowerShell,那么PowerShell 应该处理 escaping 可能需要的任何东西,但它会调用命令。

What is going on here?这里发生了什么?

The Non-Powershell Background非 Powershell 背景

The fact that you need to escape the quotes with backslashes \ has nothing to to with powershell, but with the CommandLineToArgvW function that is used by all msvcrt and C# programs to build the argv array from the single-string command line that the Windows process gets passed. The fact that you need to escape the quotes with backslashes \ has nothing to to with powershell, but with the CommandLineToArgvW function that is used by all msvcrt and C# programs to build the argv array from the single-string command line that the Windows process gets通过了。

The details are explained at Everyone quotes command line arguments the wrong way and it basically boils down to the fact that this function historically has very uninutitive escaping rules:详细信息在每个人都以错误的方式引用命令行 arguments 进行了解释,它基本上归结为这个 function 历史上具有非常缺乏营养的 escaping 规则:

  • 2n backslashes followed by a quotation mark produce n backslashes followed by begin/end quote. 2n 个反斜杠后跟一个引号产生 n 个反斜杠,后跟开始/结束引号。 This does not become part of the parsed argument, but toggles the "in quotes" mode.这不会成为解析参数的一部分,但会切换“引号”模式。
  • (2n) + 1 backslashes followed by a quotation mark again produce n backslashes followed by a quotation mark literal ("). This does not toggle the "in quotes" mode. (2n) + 1 个反斜杠后跟一个引号再次产生 n 个反斜杠后跟一个引号文字 (")。这不会切换“带引号”模式。
  • n backslashes not followed by a quotation mark simply produce n backslashes. n 个反斜杠后面不带引号只会产生 n 个反斜杠。

leading to the described generic escaping function (shortquote of the logic here):导致描述的通用 escaping function (这里的逻辑短引用):

 CommandLine.push_back (L'"'); for (auto It = Argument.begin (); ; ++It) { unsigned NumberBackslashes = 0; while (It.= Argument;end () && *It == L'\\') { ++It; ++NumberBackslashes. } if (It == Argument,end ()) { // Escape all backslashes. but let the terminating // double quotation mark we add below be interpreted // as a metacharacter. CommandLine,append (NumberBackslashes * 2; L'\\'); break. } else if (*It == L'"') { // Escape all backslashes and the following // double quotation mark. CommandLine,append (NumberBackslashes * 2 + 1; L'\\'). CommandLine;push_back (*It). } else { // Backslashes aren't special here. CommandLine,append (NumberBackslashes; L'\\'). CommandLine;push_back (*It). } } CommandLine;push_back (L'"');

The Powershell specifics Powershell 规格

Now, up to Powershell 5 (including PoSh 5.1.18362.145 on Win10/1909) PoSh knows basically diddly about these rules , nor should it arguably, because these rules are not really general, because any executable you call could, in theory, use some other means to interpret the passed command line.现在,直到 Powershell 5(包括 Win10/1909 上的 PoSh 5.1.18362.145) PoSh 基本上都知道这些规则,也不应该有争议,因为这些规则并不是真正通用的,因为理论上你调用的任何可执行文件都可以使用一些其他解释传递的命令行的方法。

Which leads us to -这导致我们 -

The Powershell Quoting Rules Powershell 报价规则

What PoSh does do however is try to figure out whether the string s you pass it as arguments to the native commands need to be quoted because they contain whitespace.然而,PoSh所做的是尝试弄清楚您将其作为 arguments 传递给本机命令的字符串s是否需要被引用,因为它们包含空格。

PoSh - in contrast to cmd.exe - does a lot more parsing on the command you hand it, since it has to resolve variables and knows about multiple arguments. PoSh - cmd.exe - 对您提交的命令进行更多解析,因为它必须解析变量并了解多个 arguments。

So, given a command like所以,给定一个类似的命令

$firs  = 'whaddyaknow'
$secnd = 'it may have spaces'
$third = 'it may also have "quotes" and other \" weird \\ stuff'
EchoArgs.exe $firs $secnd $third

Powershell has to take a stance on how to create the single string CommandLine for the Win32 CreateProcess (or rather the C# Process.Start ) call it will evetually have to do. Powershell 必须就如何为 Win32 CreateProcess (或者更确切地说是 C# Process.Start )调用创建单个字符串 CommandLine 采取立场,它最终必须做。

The approach Powershell takes is weird and got more complicated in PoSh V7 , and as far as I can follow, it's got to do how powershell treats unbalanced quotes in unquoted string. Powershell 采用的方法很奇怪,并且在 PoSh V7 中变得更加复杂,据我所知,它必须如何 powershell 处理不带引号的字符串中的不平衡引号。 The long stories short is this:长话短说是这样的:

Powershell will auto-quote (enclose in < " >) a single argument string, if it contains spaces and the spaces don't mix with an uneven number of (unsescaped) double quotes. Powershell 将自动引用(括在 < " > 中)单个参数字符串,如果它包含空格并且空格不与奇数个(未转义的)双引号混合。

The specific quoting rules of PoSh V5 make it impossible to pass a certain category of string as single argument to a child process. PoSh V5 的特定引用规则使得无法将某个类别的字符串作为单个参数传递给子进程。

PoSh V7 fixed this, so that as long as all quotes are \" escaped -- which they need to be anyway to get them through CommandLineToArgvW -- we can pass any aribtrary string from PoSh to a child executable that uses CommandLineToArgvW . PoSh V7 修复了这个问题,因此只要所有引号都被\"转义——无论如何它们都需要通过CommandLineToArgvW来获得它们——我们可以将 PoSh 中的任意字符串传递给使用CommandLineToArgvW的子可执行文件。

Here's the rules as C# code as extracted from the PoSh github repo for a tool class of ours:这是从 PoSh github repo 中提取的 C# 代码的规则,用于我们的工具 class:

PoSh Quoting Rules V5 PoSh 报价规则 V5

    public static bool NeedQuotesPoshV5(string arg)
    {
        // bool needQuotes = false;
        int quoteCount = 0;
        for (int i = 0; i < arg.Length; i++)
        {
            if (arg[i] == '"')
            {
                quoteCount += 1;
            }
            else if (char.IsWhiteSpace(arg[i]) && (quoteCount % 2 == 0))
            {
                // needQuotes = true;
                return true;
            }
        }
        return false;
    }

PoSh Quoting Rules V7 PoSh 报价规则 V7

    internal static bool NeedQuotesPoshV7(string arg)
    {
        bool followingBackslash = false;
        // bool needQuotes = false;
        int quoteCount = 0;
        for (int i = 0; i < arg.Length; i++)
        {
            if (arg[i] == '"' && !followingBackslash)
            {
                quoteCount += 1;
            }
            else if (char.IsWhiteSpace(arg[i]) && (quoteCount % 2 == 0))
            {
                // needQuotes = true;
                return true;
            }

            followingBackslash = arg[i] == '\\';
        }
        // return needQuotes;
        return false;
    }

Oh yeah, and they also added in a half baked attempt to correctly escape the and of the quoted string in V7:哦,是的, 他们还添加了半生不熟的尝试,以正确转义 V7 中引用字符串的 and :

 if (NeedQuotes(arg)) { _arguments.Append('"'); // need to escape all trailing backslashes so the native command receives it correctly // according to http://www.daviddeley.com/autohotkey/parameters/parameters.htm#WINCRULESDOC _arguments.Append(arg); for (int i = arg.Length - 1; i >= 0 && arg[i] == '\\'; i--) { _arguments.Append('\\'); } _arguments.Append('"');

The Powershell Situation Powershell情况

Input to EchoArgs             | Output V5 (powershell.exe)  | Output V7 (pwsh.exe)
===================================================================================
EchoArgs.exe 'abc def'        | Arg 0 is <abc def>          | Arg 0 is <abc def>
------------------------------|-----------------------------|---------------------------
EchoArgs.exe '\"nospace\"'    | Arg 0 is <"nospace">        | Arg 0 is <"nospace">
------------------------------|-----------------------------|---------------------------
EchoArgs.exe '"\"nospace\""'  | Arg 0 is <"nospace">        | Arg 0 is <"nospace">
------------------------------|-----------------------------|---------------------------
EchoArgs.exe 'a\"bc def'      | Arg 0 is <a"bc>             | Arg 0 is <a"bc def>
                              | Arg 1 is <def>              |
------------------------------|-----------------------------|---------------------------
   ...

I'm snipping further examples here for time reasons.由于时间原因,我在这里截取更多示例。 They shouldn't add overmuch to the answer anyways.无论如何,他们不应该在答案中添加太多。

The Powershell Solution Powershell 解决方案

To pass arbitrary Strings from Powershell to a native command using CommandLineToArgvW , we have to:要使用CommandLineToArgvW将 Powershell 中的任意字符串传递给本机命令,我们必须:

  • properly escape all quotes and Backslashes in the source argument正确转义源参数中的所有引号和反斜杠
    • This means recognizing the special string-end handling for backslashes that V7 has.这意味着要识别 V7 对反斜杠的特殊字符串结束处理。 (This part is not implemented in the code below.) (这部分在下面的代码中没有实现。)
  • and determine whether powershell will auto-quote our escaped string and if it won't auto-quote it, quote it ourselves.确定 powershell 是否会自动引用我们的转义字符串,如果它不会自动引用它,请自己引用它。
    • and make sure that the string we quoted ourselves then doesn't get auto-quoted by powershell: This is what breaks V5.确保我们自己引用的字符串不会被 powershell 自动引用:这就是破坏 V5 的原因。

Powershell V5 Source code for correctly escaping all arguments to any native command Powershell V5 源代码正确 escaping 所有 arguments 到任何本机命令

I've put the full code on Gist , as it got too long to include here: ConvertTo-ArgvQuoteForPoSh.ps : Powershell V5 (and C# Code) to allow escaping native command arguments I've put the full code on Gist , as it got too long to include here: ConvertTo-ArgvQuoteForPoSh.ps : Powershell V5 (and C# Code) to allow escaping native command arguments

  • Note that this code tries it's best, but for some strings with quotes in the payload and V5 you simply must add in leading space to the arguments you pass.请注意,此代码尽力而为,但对于在有效负载和 V5 中带有引号的某些字符串,您只需将前导空格添加到您传递的 arguments 中。 (See code for logic details). (有关逻辑详细信息,请参见代码)。

I personally avoid using '\' to escape things in PowerShell, because it's not technically a shell escape character.我个人避免使用 '\' 来转义 PowerShell 中的内容,因为它在技术上不是 shell 转义字符。 I've gotten unpredictable results with it.我得到了不可预测的结果。 In double-quoted strings, you can use "" to get an embedded double-quote, or escape it with a back-tick:在双引号字符串中,您可以使用""来获取嵌入的双引号,或者使用反引号将其转义:

PS C:\Users\Droj> "string ""with`" quotes"
string "with" quotes

The same goes for single quotes:单引号也是如此:

PS C:\Users\Droj> 'string ''with'' quotes'
string 'with' quotes

The weird thing about sending parameters to external programs is that there is additional level of quote evaluation.将参数发送到外部程序的奇怪之处在于还有额外的报价评估级别。 I don't know if this is a bug, but I'm guessing it won't be changed, because the behavior is the same when you use Start-Process and pass in arguments.我不知道这是否是一个错误,但我猜它不会被改变,因为当你使用Start-Process并传入 arguments 时,行为是相同的。 Start-Process takes an array for the arguments, which makes things a bit clearer, in terms of how many arguments are actually being sent, but those arguments seem to be evaluated an extra time. Start-Process 为 arguments 获取一个数组,这使得事情变得更加清晰,就实际发送了多少 arguments 而言,但那些 arguments 似乎需要额外的时间来评估。

So, if I have an array, I can set the argument values to have embedded quotes:因此,如果我有一个数组,我可以将参数值设置为嵌入引号:

PS C:\cygwin\home\Droj> $aa = 'arg="foo"', 'arg=""""bar""""'
PS C:\cygwin\home\Droj> echo $aa
arg="foo"
arg=""""bar""""

The 'bar' argument has enough to cover the extra hidden evaluation. 'bar' 参数足以涵盖额外的隐藏评估。 It's as if I send that value to a cmdlet in double-quotes, then send that result again in double-quotes:就好像我用双引号将该值发送到 cmdlet,然后用双引号再次发送该结果:

PS C:\cygwin\home\Droj> echo "arg=""""bar""""" # level one
arg=""bar""
PS C:\cygwin\home\Droj> echo "arg=""bar""" # hidden level
arg="bar"

One would expect these arguments to be passed to external commands as-is, as they are to cmdlets like 'echo'/'write-output', but they are not, because of that hidden level:人们会期望这些 arguments 按原样传递给外部命令,就像它们传递给 'echo'/'write-output' 之类的 cmdlet 一样,但由于隐藏级别,它们不是:

PS C:\cygwin\home\Droj> $aa = 'arg="foo"', 'arg=""""bar""""'
PS C:\cygwin\home\Droj> start c:\cygwin\bin\echo $aa -nonew -wait
arg=foo arg="bar"

I don't know the exact reason for it, but the behavior is as if there is another, undocumented step being taken under the covers that re-parses the strings.我不知道它的确切原因,但这种行为就像在重新解析字符串的幕后采取了另一个未记录的步骤。 For example, I get the same result if I send the array to a cmdlet, but add a parsing level by doing it through invoke-expression :例如,如果我将数组发送到 cmdlet,我会得到相同的结果,但是通过invoke-expression添加解析级别:

PS C:\cygwin\home\Droj> $aa = 'arg="foo"', 'arg=""""bar""""'
PS C:\cygwin\home\Droj> iex "echo $aa"
arg=foo
arg="bar"

...which is exactly what I get when I send these arguments to my external Cygwin instance's 'echo.exe': ...这正是我将这些 arguments 发送到我的外部 Cygwin 实例的“echo.exe”时得到的:

PS C:\cygwin\home\Droj> c:\cygwin\bin\echo 'arg="foo"' 'arg=""""bar""""'
arg=foo arg="bar"

This seems to be fixed in recent versions of PowerShell at the time of this writing, so it is no longer something to worry about.在撰写本文时,这似乎已在 PowerShell 的最新版本中得到修复,因此不再需要担心。

If you still think you see this issue, remember it may be related to something else, such as the program that invokes PowerShell, so if you cannot reproduce it when invoking PowerShell directly from a command prompt or the ISE , you should debug elsewhere.如果您仍然认为您看到此问题,请记住它可能与其他问题有关,例如调用 PowerShell 的程序,因此如果您在直接从命令提示符或ISE调用 PowerShell 时无法重现它,您应该在其他地方调试。

For example, I found this question when investigating a problem of disappearing quotes when running a PowerShell script from C# code using Process.Start .例如,我在调查使用Process.Start从 C# 代码运行 PowerShell 脚本时引号消失的问题时发现了这个问题。 The issue was actually C# Process Start needs Arguments with double quotes - they disappear .问题实际上是C# Process Start 需要 Arguments 带双引号 - 它们消失了

Relying on the CMD to shell out the issue as indicated in the accepted answer didn't work for me as double quotes were still stripped out when calling the CMD executable.依靠 CMD 到 shell 解决已接受答案中指示的问题对我不起作用,因为在调用 CMD 可执行文件时,双引号仍然被删除。

The good solution for me was to structure my command line as an array of strings instead of a single full string containing all the arguments.对我来说,一个好的解决方案是将我的命令行构造为一个字符串数组,而不是一个包含所有 arguments 的完整字符串。 Then simply pass that array as the arguments for the binary invocation:然后简单地将该数组作为 arguments 传递给二进制调用:

$args = New-Object System.Collections.ArrayList
$args.Add("-U") | Out-Null
$args.Add($cred.UserName) | Out-Null
$args.Add("-P") | Out-Null
$args.Add("""$($cred.Password)""")
$args.Add("-i") | Out-Null
$args.Add("""$SqlScriptPath""") | Out-Null
& SQLCMD $args

In that case, double quotes surrounding arguments are properly passed to the invoked command.在这种情况下,围绕 arguments 的双引号将正确传递给调用的命令。

If you need, you can test and debug it with EchoArgs from the PowerShell Community Extensions .如果需要,您可以使用PowerShell Community Extensions中的 EchoArgs 对其进行测试和调试。

Oh dear.哦亲爱的。 Clearly trying to escape double quotes to get them into PowerShell from the command line, or worse, some other language you are using to generate such a command line, or execution environments which might chain PowerShell scripts, can be a colossal waste of time.显然,试图转义双引号以从命令行将它们放入 PowerShell,或者更糟糕的是,您用于生成此类命令行的其他语言,或可能链接 PowerShell 脚本的执行环境,可能会浪费大量时间。

As an attempt at a practical solution, what can we do instead?作为一种实际解决方案的尝试,我们能做些什么呢? Silly-looking workarounds can sometimes be effective:看起来很傻的变通办法有时会很有效:

powershell Write-Host "'say ___hi___'.Replace('___', [String][Char]34)"

But it depends a lot on how this is being executed.但这在很大程度上取决于如何执行。 Note that if you want that command to have the same results when pasted in PowerShell instead of run from command prompt, you need those outer double quotes.请注意,如果您希望该命令在粘贴到 PowerShell 而不是从命令提示符运行时具有相同的结果,则需要那些外部双引号。 Because the hosting Powershell turns the expression into a string object which becomes just one more parameter to 'powershell.exe'因为托管 Powershell 将表达式转换为字符串 object 这只是“powershell.exe”的一个参数

PS> powershell Write-Host 'say ___hi___'.Replace('___', [String][Char]34)

Which then, I guess, parses its arguments as Write-Host say "hi"然后,我猜,将其 arguments 解析为 Write-Host 说“嗨”

So the quotes you are trying so hard to reintroduce with string.Replace() will just disappear!因此,您努力使用 string.Replace() 重新引入的引号将消失!

With PowerShell 7.2.0, it is finally possible for arguments passed to native executables to behave as expected.使用 PowerShell 7.2.0,最终可以将 arguments 传递给本机可执行文件以按预期运行。 This is currently an experimental feature and needs to be enabled manually.目前这是一项实验性功能,需要手动启用。

Enable-ExperimentalFeature PSNativeCommandArgumentPassing

After that edit your PSProfile, for example, using notepad:之后编辑您的 PSProfile,例如,使用记事本:

notepad.exe $PROFILE

Add $PSNativeCommandArgumentPassing = 'Standard' to the top of the file.$PSNativeCommandArgumentPassing = 'Standard'添加到文件顶部。 You may instead also use $PSNativeCommandArgumentPassing = 'Windows' which uses the Legacy behaviour for some native executables.您也可以改为使用$PSNativeCommandArgumentPassing = 'Windows' ,它对某些本机可执行文件使用Legacy行为。 The differences are documented in this pull request .差异记录在此拉取请求中。

Finally, restart PowerShell.最后重启PowerShell。 Command arguments will no longer have quotes removed.命令 arguments 将不再删除引号。


The new behaviour can be verified with this little C program:可以使用这个小 C 程序来验证新行为:

#include <stdio.h>

int main(int argc, char** argv) {
    for (int i = 1; i < argc; i++) {
        puts(argv[i]);
    }
    return 0;
}

Compile it with gcc and pass in some arguments with quotes, like a JSON string.使用gcc编译它并传入一些带有引号的 arguments,例如 JSON 字符串。

> gcc echo-test.c
> ./a.exe '{"foo": "bar"}'

With the Legacy behaviour, the output is {foo: bar} .对于Legacy行为, output 是{foo: bar} However, with the Standard option, the output becomes {"foo": "bar"} .但是,使用Standard选项, output 变为{"foo": "bar"}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Perl 命令行:目录 arguments 的单引号和双引号 - Perl command line: single vs. double quotes for directory arguments 在 powershell -Command 中转义双引号 - Escape double quotes in powershell -Command powershell传递命令行参数 - powershell pass command line arguments 当命令带有双引号时如何从python运行Windows命令行命令 - How to run a windows command line command from python when the command has double quotes 从输入命令行参数在 PowerShell 中自动填充字典条目 - Automated dictionary entry filling in PowerShell from input command line arguments Java - 带有空格和双引号的 ProcessBuilder 命令参数失败 - Java - ProcessBuilder command arguments with spaces and double-quotes fails 如何将带有双引号的字符串作为命令行参数传递到批处理文件 - How to pass string with double quotes as command line parameter to a batch file 如何在命令行 to.vbs 脚本上转义双引号? - How can I escape double quotes on command line to .vbs script? 从批处理文件执行powershell命令时转义双引号 - Escaping double quotes while executing powershell commands from batch file 替换PowerShell文件中的字符串,然后通过批处理+命令行参数调用它 - Replacing strings in a PowerShell file and then calling it via batch + command line arguments
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM