从powershell.exe将参数传递给脚本

时间:2016-01-27 13:11:40

标签: powershell parameter-passing command-line-arguments

我有一个这样的脚本:

param(
[string]$root,
[string]$bin,
[string]$out,
[string]$zdir
)


echo "args..."
echo "Root: $root", "zdir: $zdir", "out: $out", "bin: $bin"

我调用它如下:

powershell.exe -nologo -noprofile -file "C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\zip.ps1" -root "C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\" -zdir "Zip" -out "output.zip" -bin "C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\bin\Debug\" 

但我的输出恰恰相反:

C:\code\misc>powershell.exe -nologo -noprofile -file "C:\Users\arun_jayapal\Docu
ments\Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\zip.ps1" -root "
C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompass\Outlo
okCompass\" -zdir "Zip" -out "output.zip" -bin "C:\Users\arun_jayapal\Documents\
Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\bin\Debug\"
args...
Root: C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompas
s\OutlookCompass" -zdir Zip -out output.zip -bin C:\Users\arun_jayapal\Document
s\Visual
zdir:
out: 2013\Projects\OutlookCompass\OutlookCompass\bin\Debug"
bin: Studio

2 个答案:

答案 0 :(得分:1)

您的问题是您正在从cmd.exe调用powershell脚本,对于许多旧版.exe程序,序列\"用于将引用转义为参数。 Powershell尊重此约定,因此当您调用Powershell.exe时,您必须遵循此转义约定。

所以:

-root "something\" -zdir "Zip" -out "output.zip" -bin "something\"

包含两个双引号的单个参数是否使用\"转义到字符串中。 cmd删除了其他双引号,因此Zipoutput.zip是引号之外的字符串,但由于它们不包含任何空格,因此它们不会拆分参数。

这应该有效:

-root "something\\" -zdir "Zip" -out "output.zip" -bin "something\\"

在引号之前加倍反斜杠意味着会传递一个反斜杠,并且引号会失去其特殊含义。不要将任何其他反斜杠加倍,因为当cmd中的一个或多个序列在双引号之前时,powershell仅将反斜杠视为特殊。

或者,不要使用尾部反斜杠,并将它们插入脚本中的所需位置。

或者只使用cmd本身作为主命令提示符并完全抛弃-EncodedCommand

顺便说一句,如果你从内部调用另一个powershell副本,它被认为是特殊的东西,参数在base64中编码并通过 $scope.module.discount = [{ licences: 0, discountPercentage: 0, new_value_pr_licence: 0 }] 命令行选项传递,所以在这种情况下没有必要担心逃脱报价。

答案 1 :(得分:0)

Duncan's helpful answer包含关键指针(以及有用的背景信息):参数值末尾的 \"被解释为转义 {{ 1}},导致参数边界被误解

您的选项是:

  • 在每个参数值的末尾使用"代替\\",如Duncan建议的那样(例如,\"
  • 完全忽略路径中的尾随"c:\foo bar\\"(例如,\而不是"c:\foo bar"
  • 如果您想避免修改参数值,请使用以下单引号解决方案(在v3上验证)。

单引号解决方案:

这假设您从"c:\foo bar\"调用此函数,无论是从批处理文件还是在命令提示符处(在PowerShell中,您只能使用cmd.exe

  • 使用单个引号而不是双引号
  • 使用& <script> ...参数代替-Command
  • 使用-File作为脚本路径的前缀(使用&进行转义,让^将其视为文字)
cmd.exe
  • 这是有效的,因为通过使用powershell.exe -noprofile -command ^& 'C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\zip.ps1' -root 'C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\' -zdir 'Zip' -out 'output.zip' -bin 'C:\Users\arun_jayapal\Documents\Visual Studio 2013\Projects\OutlookCompass\OutlookCompass\bin\Debug\' (和PowerShell&#39; s -Command(调用)运算符来调用其路径具有嵌入空格的脚本),命令行的其余部分可以使用单引号字符串引用PowerShell样式,这些字符串不受解释(甚至不能通过解析PowerShell自身启动命令行解析的C样式参数解析,但嵌入式{除外} {1}}字符。 - 见下文)。

  • 使用此方法需要转义的唯一字符是:

    • 使用&在参数中嵌入文字"
    • 使用''在参数中嵌入文字'
    • 如果你需要逃避\"字符。保护他们免受"解释作为环境变量引用的一部分(无论您使用的是单引号还是双引号,都必须执行此操作),请参阅我的this answer
  • 请注意,为了在当前目录中执行脚本,必须% - 在脚本文件名前加上前缀,就像在PowerShell中一样。