2016-01-27 16 views
1

參數傳遞到腳本我有一個這樣的腳本:從powershell.exe

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 
+1

變量'$ root'容納整個應牽住' 「C:\用戶\ arun_jayapal \文檔\的Visual Studio 2013 \項目\ OutlookCompass \ OutlookCompass \」'但那不是什麼輸出... – deostroll

回答

0

Duncan's helpful answer包含關鍵指針(和有用的背景信息爲好):\"在參數值的端部被解釋爲轉義",這會導致參數的邊界被誤解

選項有:

  • 使用\\"代替\"在每個參數值的末尾,如鄧肯建議(例如,"c:\foo bar\\"
  • 省略後面從路徑\完全(例如的"c:\foo bar"代替"c:\foo bar\"
  • 如果你想避免修改參數值,請使用以下,單引號解決方案(在V3驗證)。

單引號的解決方案:

這是假設你從cmd.exe調用此,無論是從一個批處理文件或在命令提示符(內部PowerShell中,你可以只使用& <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的&(調用)操作符來調用其路徑嵌入空格的腳本),命令行的其餘部分可以引用PowerShell風格,這些字符串不受解釋的影響(甚至沒有通過PowerShell自己的啓動命令行解析的C風格參數解析,除了嵌入式"字符。 - 見下文)。

  • 是需要這種方法逃避的字符只有:

    • 使用''嵌入文字'參數內。
    • 使用\"在參數中嵌入文字"
    • 如果您需要轉義%字符。作爲環境變量引用的一部分(無論您使用單引號字符串還是雙引號字符串,您都必須執行該操作),從而保護它們免受cmd.exe的解釋,請參閱我的this answer
  • 請注意,爲了在當前目錄中執行腳本,您必須使用.\ -prefix腳本文件名,就像在PowerShell中那樣。

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

順便說一句,如果你從本身內部調用powershell的另一個副本,它會被識別爲特殊的東西,參數在base64中編碼,並通過-EncodedCommand命令行選項傳遞,所以在這種情況下,不需要擔心轉義引號。

+0

我在Visual Studio中運行這個...所以你現在建議我做什麼? – deostroll

+1

您是否從程序生成命令行?如果是這樣,你可以使用'-EncodedCommand'命令行參數並傳遞參數字符串base64編碼。 – Duncan

+1

@ mklement0,是的,我試圖改進我的答案的那一部分。奇怪的處理''''實際上來自Microsoft的C運行時庫,所以它對大多數'.exe'程序來說是很常見的,但它是這種可執行文件的約定,而不是'cmd.exe'本身的一個方面。 – Duncan

相關問題