使用PowerShell.exe的启动过程在嵌入的单引号和双引号中表现出不同的行为 [英] Start-Process with PowerShell.exe exhibits different behavior with embedded single quotes and double quotes
问题描述
首先,如果有人想知道为什么我们要以这种方式调用PowerShell,我会使用我们正在构建的更复杂的命令来遇到这种行为,但是可以使用一个更简单的示例来展示该行为,如下所示.实际上,我们在32位PowerShell下以admin身份运行命令,并在字符串中呈现了其他变量(因此,为什么我不简单地在外部使用单引号),但这似乎并没有行为如下.
First, in case anyone wonders why we're invoking PowerShell in this way, I ran into this behavior with a more complex command we were building, but the behavior can be exhibited using a more simple example as shown below. In practice, we are running a command under 32-bit PowerShell as admin with additional variables rendered in the string (hence why I don't simply use single-quotes for the outer portion), but that doesn't seem to factor into the behavior below.
当我通过 Start-Process
调用PowerShell时,如果在PowerShell可执行文件的 -Command
参数周围使用单引号,则会出现一些奇怪的行为.例如:
When I invoke PowerShell through Start-Process
, I get some odd behaviors if I use single quotes surrounding the -Command
parameter to the PowerShell executable. For example:
Start-Process -FilePath Powershell.exe -ArgumentList "-Command 'ping google.com'"
仅将 ping google.com
呈现为输出并退出.但是,如果我使用嵌套的双引号而不是单引号,如下所示:
just renders ping google.com
as the output and exits. However, if I use nested double-quotes instead of the single-quotes as follows:
Start-Process -FilePath Powershell.exe -ArgumentList "-Command `"ping google.com`""
ping
运行并产生预期的输出:
ping
runs and produces the expected output:
使用32个字节的数据对google.com [173.194.78.113]执行Ping操作:
Pinging google.com [173.194.78.113] with 32 bytes of data:
从173.194.78.113中回复:字节= 32时间= 34ms TTL = 45
Reply from 173.194.78.113: bytes=32 time=34ms TTL=45
从173.194.78.113中回复:字节= 32时间= 33ms TTL = 45
Reply from 173.194.78.113: bytes=32 time=33ms TTL=45
从173.194.78.113中回复:字节= 32时间= 35ms TTL = 45
Reply from 173.194.78.113: bytes=32 time=35ms TTL=45
从173.194.78.113中回复:字节= 32时间= 32ms TTL = 45
Reply from 173.194.78.113: bytes=32 time=32ms TTL=45
Ping统计为173.194.78.113:
Ping statistics for 173.194.78.113:
数据包:已发送= 4,已接收= 4,丢失= 0(丢失0%),
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
大约往返时间(以毫秒为单位):
Approximate round trip times in milli-seconds:
最小值= 32毫秒,最大值= 35毫秒,平均值= 33毫秒
Minimum = 32ms, Maximum = 35ms, Average = 33ms
如果我在 -Command
参数中使用单引号而不是双引号,为什么命令字符串只是按原样呈现而不是执行?
Why does the command string simply render as-is instead of execute if I use the single-quotes for the -Command
parameter instead of double-quotes?
推荐答案
js2010的有用答案在使用上是正确的 Start-Process
的代码与您的问题有关,并且行为特定于PowerShell的 CLI ( pwsh
( PowerShell [Core] 6 + ):
js2010's helpful answer is correct in that the use of Start-Process
is incidental to your question and that the behavior is specific to PowerShell's CLI (powershell.exe
for Windows PowerShell, and pwsh
for PowerShell [Core] 6+):
在Windows上 [1] ,需要评估 两个层:
On Windows[1], there are two layers of evaluation to consider:
-
(a)将命令行初始解析为参数.
(b)由于使用了 -Command
( -c
)CLI参数.
(b) The evaluation of the (space-concatenated) resulting arguments as PowerShell code, due to use of the
-Command
(-c
) CLI parameter.
关于(a):
与Windows上的大多数控制台程序一样,PowerShell仅将"
字符(双引号)识别-还将'
(单引号)识别为 syntactic函数. [2]
As most console programs on Windows do, PowerShell recognizes only "
chars. (double quotes) - not also '
(single quotes) - as having syntactic function.[2]
-
也就是说,除非将
"
字符转义为 ,否则它们是字符串定界符,而它们本身也会被删除.
That is, unless
"
chars. are escaped, they are string delimiters that themselves are removed during parsing.
如上所暗示,'
字符.被未删除.
As implied by the above, '
chars. are not removed.
无论参数是什么-可能是"
剥离标记的数组-都是级联,它们之间有一个单个空格,(b)的输入.
Whatever arguments are the result - an array of possibly "
-stripped tokens - are concatenated with a single space between them, which becomes the input for (b).
要在您的示例上下文中对此进行解释,请从图片中取出 Start-Process
:
To explain this in the context of your example, with Start-Process
taken out of the picture:
注意:以下适用于从 cmd.exe
或涉及 no shell的任何上下文中调用(包括 Start-Process
和Windows Run( WinKey-R )对话框).相比之下,如果需要, PowerShell 重新引用在幕后的命令行以始终使用"
.
换句话说:以下内容适用于命令行 PowerShell 所见.
Note: The following applies to calling from cmd.exe
or any context where no shell is involved (including Start-Process
and the Windows Run (WinKey-R) dialog). By contrast, PowerShell re-quotes the command line behind the scenes to always use "
, if needed.
To put it differently: the following applies to command lines as seen by PowerShell.
单-引用的命令:
Single-quoted command:
# Note: This *would* work for calling ping if run from
# (a) PowerShell itself or (b) from a POSIX-like shell such as Bash.
# However, via cmd.exe or any context where *no* shell is involved,
# notably Start-Process and the Windows Run dialog, it does not.
powershell -Command 'ping google.com'
-
(a)使PowerShell查找以下两个逐字参数:
'ping
和google.com'
(b)将这些逐字自变量连接起来,形成
'ping google.com'
[2] 并执行作为PowerShell代码,因此输出此字符串文字的内容,ping google.com
(b) concatenates these verbatim arguments to form
'ping google.com'
[2] and executes that as PowerShell code, therefore outputs the content of this string literal,ping google.com
双-引用的命令:
Double-quoted command:
powershell -Command "ping google.com"
-
(a)使PowerShell剥离 syntactic
"
字符,找到以下单个逐字参数:ping google.com
(a) results in PowerShell stripping the syntactic
"
characters, finding the following, single verbatim argument:ping google.com
(b)导致该逐字自变量-
ping google.com
-作为PowerShell代码执行,因此会导致命令调用,即参数为google.com
的ping
可执行文件的内容.(b) then results in this verbatim argument -
ping google.com
- being executed as PowerShell code, which therefore results in a command invocation, namely of theping
executable with argumentgoogle.com
.[1]在类Unix平台上,第一层不适用,因为被调用的程序只会看到 verbatim 参数的 array ,而不是他们自己必须解析为参数的命令行.并不是说,如果您从类似POSIX的外壳(例如在类似Unix的平台上的
bash
)调用PowerShell CLI,那么正是那个外壳将单引号识别为字符串定界符,并在 PowerShell看到它们之前将它们剥离.[1] On Unix-like platforms, the first layer doesn't apply, because programs being invoked only ever see an array of verbatim arguments, not a command line that they themselves must parse into arguments. Not that if you call the PowerShell CLI from a POSIX-like shell such as
bash
on Unix-like platforms, it is that shell that recognizes single-quotes as string delimiters, and strips them before PowerShell sees them.[2]令人惊讶的是,在Windows上,最终由每个单独的程序来解释命令行,并且某些 do 选择还识别
>'
作为字符串定界符(例如Ruby).但是,Windows上的许多程序(包括PowerShell本身)都基于C运行时,该运行时仅识别"
.[2] Surprisingly, on Windows it is ultimately up to each individual program to interpret the command line, and some do choose to also recognize
'
as string delimiters (e.g., Ruby). However, many programs on Windows - including PowerShell itself - are based on the C runtime, which only recognizes"
.[3]另外,请注意,这意味着正在进行空白空间标准化:即,
powershell-命令'ping google.com'
同样会导致'ping google.com'
.[3] As an aside, note that this implies that whitespace normalization is taking place: that is,
powershell -Command 'ping google.com'
would equally result in'ping google.com'
.这篇关于使用PowerShell.exe的启动过程在嵌入的单引号和双引号中表现出不同的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
-