2016-04-25 94 views
1

我正在使用Invoke-Command在遠程服務器上執行PowerShell表達式。執行命令時出現正則表達式錯誤。看起來好像powershell在內部使用RegEx來分析參數,但由於某種原因,它在這種情況下失敗。Powershell調用命令導致RegEx錯誤

特別令人困惑的是,在Invoke-Command調用中根本沒有使用看起來導致解析錯誤的變量。我的猜測是某種變量捕獲正在發生,因此可以在遠程執行的腳本中引用變量(通過「使用」範圍),並且這對我的$ ArtifactDirectory參數是失敗的。我知道這是導致問題的$ ArtifactDirectory param,只是因爲異常中「regex表達式」的值是$ ArtifactDirectory參數的值。

另一個重要的注意事項是我可以在TFS正在執行的同一臺機器上手動運行腳本(使用完全相同的參數值),而不會出錯。這告訴我這是某種會話選項,導致TFS構建/部署代理正在設置的問題。

下面是PowerShell腳本的相關部分:

param(
    [string] $ArtifactDirectory, 
    [string] $ComputerName 
    ) 

$someFancyCommand = "this does not seem to matter" 

Invoke-Command -ComputerName $ComputerName -ScriptBlock { 
    Invoke-Expression "$using:someFancyCommand" 
} 

這裏是我如何執行它(在這種情況下,通過TFS發佈管理):

MyScript.ps1 -ArtifactDirectory "C:\MSAgent\_work\66f1e4ebb\Cc - (WIP)\CC - My Cool App" -ComputerName "SomeComputer" 

這裏完整的堆棧跟蹤:

2016-04-25T13:53:28.6024146Z [Exception:System.Management.Automation.RuntimeException: The regular 
2016-04-25T13:53:28.6024146Z expression pattern {{C:\MSAgent\_work\66f1e4ebb\Cc - (WIP)\CC - My Cool App}} is not valid. ---> 
2016-04-25T13:53:28.6024146Z System.ArgumentException: parsing "{{C:\MSAgent\_work\66f1e4ebb\Cc - (WIP)\CC - My Cool App}}" - 
2016-04-25T13:53:28.6024146Z Unrecognized escape sequence \M. 
2016-04-25T13:53:28.6024146Z at System.Text.RegularExpressions.RegexParser.ScanCharEscape() 
2016-04-25T13:53:28.6024146Z at System.Text.RegularExpressions.RegexParser.ScanBasicBackslash() 
2016-04-25T13:53:28.6024146Z at System.Text.RegularExpressions.RegexParser.ScanRegex() 
2016-04-25T13:53:28.6024146Z at System.Text.RegularExpressions.RegexParser.Parse(String re, RegexOptions op) 
2016-04-25T13:53:28.6024146Z at System.Text.RegularExpressions.Regex..ctor(String pattern, RegexOptions options, TimeSpan matchTimeout, Boolean 
2016-04-25T13:53:28.6024146Z useCache) 
2016-04-25T13:53:28.6024146Z at System.Text.RegularExpressions.Regex..ctor(String pattern, RegexOptions options) 
2016-04-25T13:53:28.6024146Z at System.Management.Automation.ParserOps.NewRegex(String patternString, RegexOptions options) 
2016-04-25T13:53:28.6024146Z at System.Management.Automation.ParserOps.ReplaceOperator(ExecutionContext context, IScriptExtent errorPosition, 
2016-04-25T13:53:28.6226512Z Object lval, Object rval, Boolean ignoreCase) 
2016-04-25T13:53:28.6226512Z --- End of inner exception stack trace --- 
2016-04-25T13:53:28.6226512Z at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception 
2016-04-25T13:53:28.6226512Z exception) 
2016-04-25T13:53:28.6226512Z at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame) 
2016-04-25T13:53:28.6226512Z at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) 
2016-04-25T13:53:28.6226512Z at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) 
2016-04-25T13:53:28.6226512Z at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame) 
2016-04-25T13:53:28.6226512Z at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0) 
2016-04-25T13:53:28.6336645Z at System.Management.Automation.ScriptBlock.InvokeWithPipeImpl(ScriptBlockClauseToInvoke clauseToInvoke, Boolean 
2016-04-25T13:53:28.6336645Z createLocalScope, Dictionary`2 functionsToDefine, List`1 variablesToDefine, ErrorHandlingBehavior 
2016-04-25T13:53:28.6336645Z errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo 
2016-04-25T13:53:28.6336645Z invocationInfo, Object[] args) 
2016-04-25T13:53:28.6336645Z at System.Management.Automation.ScriptBlock.<>c__DisplayClassa.<InvokeWithPipe>b__8() 
2016-04-25T13:53:28.6336645Z at System.Management.Automation.Runspaces.RunspaceBase.RunActionIfNoRunningPipelinesWithThreadCheck(Action action) 
2016-04-25T13:53:28.6336645Z at System.Management.Automation.ScriptBlock.InvokeWithPipe(Boolean useLocalScope, ErrorHandlingBehavior 
2016-04-25T13:53:28.6336645Z errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Pipe outputPipe, InvocationInfo 
2016-04-25T13:53:28.6336645Z invocationInfo, Boolean propagateAllExceptionsToTop, List`1 variablesToDefine, Dictionary`2 functionsToDefine, Object[] 
2016-04-25T13:53:28.6336645Z args) 
2016-04-25T13:53:28.6336645Z at System.Management.Automation.ScriptBlock.InvokeUsingCmdlet(Cmdlet contextCmdlet, Boolean useLocalScope, 
2016-04-25T13:53:28.6336645Z ErrorHandlingBehavior errorHandlingBehavior, Object dollarUnder, Object input, Object scriptThis, Object[] args) 
2016-04-25T13:53:28.6336645Z at Microsoft.PowerShell.Commands.ForEachObjectCommand.ProcessRecord() 
2016-04-25T13:53:28.6336645Z at System.Management.Automation.CommandProcessor.ProcessRecord()] 
+0

我想看看你如何用'$ ArtifactDirectory'生成'$ someFancyCommand'的例子嗎?我想如果你真的運行了上面列表中的命令,錯誤是不同的。還有爲什麼'invoke-expression'?爲什麼不只是「命令」? – Matt

+0

對於$ someFancyCommand,$ ArtifactDirectory不被使用*。該$ ArtifactDirectory在Invoke-Command調用後的很長時間內在MyScript.ps1中的其他地方使用。正在執行的表達式基本上是一個TopShelf命令行來啓動/停止/安裝等Windows服務。表達式本身看起來像「&'c:\ myapp \ host.exe'start」。正如我在我的文章中提到的那樣,命令本身似乎並不重要 - 我可以用一個簡單的寫主機代替它,它根本不使用變量,它仍然失敗。 當你說「爲什麼不只是 - 命令」,你指的是什麼? – RMD

+0

如果錯誤與'$ ArtifactDirectory'相關,那我們爲什麼不看它在使用中(如果錯誤來自PowerShell)?我假設他們是相關的,並且你只是運行一些exe文件,所以我質疑你對IEX的使用。 'Invoke-Command -Command'在這種情況下也會起作用......我又試圖弄清楚變量與代碼的關係。我對TFS一無所知,這可能只是我的無知。錯誤來自TFS發佈管理嗎? – Matt

回答

0

我試過了,它與普通的PowerShell一起工作。正如你在你的問題中指出的那樣,這絕對是TFS Release管理問題,它是對輸入參數的處理。

分辨率/工作範圍:請嘗試轉義路徑"C:\MSAgent\_work\66f1e4ebb\Cc - (WIP)\CC - My Cool App"中的所有特殊字符。 PowerShell中的轉義序列是字符\

爲了您的方便起見,這裏的路徑應該怎麼看起來像轉義序列:

"C:\\MSAgent\\_work\\66f1e4ebb\\Cc - \(WIP\)\\CC - My Cool App" 
1

我結束了重寫整個劇本,並神奇地,錯誤就走開了。正如其他人指出的,嘗試上述腳本的簡單版本可以正常工作。事實上,它既可以通過TFS Release手動執行也可以執行。

最後,錯誤似乎與腳本中後面的文件複製操作有關 - 但該文件複製操作正常工作如果上述Invoke-Command調用已被刪除。

所以我不知道發生了什麼事,但有遠程命令的執行,下面的腳本的後續執行之間的相互作用:

Get-ChildItem -Path $sourceDirectory -Recurse -Exclude $exclude | 
    Copy-Item -Destination { 
     if ($_.PSIsContainer) { 
      Join-Path $ArtifactDirectory $_.Parent.FullName.Substring($sourceDirectory.length) 
     } else { 
      Join-Path $ArtifactDirectory $_.FullName.Substring($sourceDirectory.length) 
     } 
    } -Force -Exclude $exclude -Verbose 

無論如何,我重構上述腳本轉化爲模塊/功能,問題完全消失。