Powershell – 转义string传递给subprocess

我花了一些时间搞清楚Powershell脚本的正确语法。 但最后它是试错法,我想知道为什么下面的语法不起作用。

该脚本以提升模式启动新的Powershel并设置环境variables。 这是摘录:

$x = "NewValue" $arguments = "-NoExit", "-command", "&{ [Environment]::SetEnvironmentVariable(`"MyVar1`", `"$x`", [EnvironmentVariableTarget]::Machine) }" Start-Process powershell -Verb runAs -ArgumentList $arguments 

如果我只是打印出variables$arguments ,这是一个数组,我所期望的:

 -NoExit -command &{ [Environment]::SetEnvironmentVariable("MyVar1", "NewValue", [EnvironmentVariableTarget]::Machine) } 

然而,在小孩Powershell双引号被吃掉了不知何故和失踪。 为什么? 这是预期的行为? 它输出:

 At line:1 char:42 + &{ [Environment]::SetEnvironmentVariable(MyVar1, NewValue, [EnvironmentVariableT ... + ~ Missing ')' in method call. At line:1 char:42 + &{ [Environment]::SetEnvironmentVariable(MyVar1, NewValue, [EnvironmentVariableT ... + ~~~~~~ Unexpected token 'MyVar1' in expression or statement. At line:1 char:48 + &{ [Environment]::SetEnvironmentVariable(MyVar1, NewValue, [EnvironmentVariableT ... + ~ Missing argument in parameter list. At line:1 char:2 + &{ [Environment]::SetEnvironmentVariable(MyVar1, NewValue, [EnvironmentVariableT ... + ~ Missing closing '}' in statement block. At line:1 char:96 + ... arget]::Machine) } + ~ Unexpected token ')' in expression or statement. At line:1 char:98 + ... get]::Machine) } + ~ Unexpected token '}' in expression or statement. + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : MissingEndParenthesisInMethodCall 

我的环境:

 > $PSVersionTable Name Value ---- ----- PSVersion 4.0 WSManStackVersion 3.0 SerializationVersion 1.1.0.1 CLRVersion 4.0.30319.42000 BuildVersion 6.3.9600.17400 PSCompatibleVersions {1.0, 2.0, 3.0, 4.0} PSRemotingProtocolVersion 2.2 

================================================== =============

作为参考,这里的工作版本使用单引号,而不是双引号(我也删除了-NoExit参数,这只是为了debugging):

 $x = "NewValue" $arguments = "-command", "&{ [Environment]::SetEnvironmentVariable('MyVar1', `'$x`', [EnvironmentVariableTarget]::Machine) }" Start-Process powershell -Verb runAs -ArgumentList $arguments 

PowerShell.exe是如何parsing其命令行的。 它主要遵循命令行parsing的.NET规则 :

  • 空间是一个论据分隔符。 无论您使用多less个空格来分隔参数, PowerShell.exe都会通过单个空间来连接各个参数。

     CMD> PowerShell -Command echo 'multiple spaces' multiple spaces 
  • 如果要在参数值中包含空格,则应该用双引号括起空格。 双引号本身不是结果参数值的一部分,可以是参数内的任何地方:

     CMD> PowerShell -Command echo 'mult"iple spa"ces' multiple spaces 
  • 如果你希望字面双引号是参数值的一部分,那么你必须用反斜线来转义它:

     CMD> PowerShell -Command echo 'literal\"double\"quotes' literal"double"quotes 
  • 如果你希望字面反斜杠在双引号之前,那么你必须用另一个反斜线来反斜线。 除此之外,反斜杠字面解释,不需要转义:

     CMD> PowerShell -Command echo 'back\\slash\\" something\\else\\"' back\\slash\ something\\else\