【发布时间】:2016-04-25 14:10:58
【问题描述】:
我正在使用 Invoke-Command 在远程服务器上执行 powershell 表达式。命令执行时出现正则表达式错误。似乎 powershell 在内部使用 RegEx 来解析参数,但由于某种原因,它在这种情况下失败了。
特别令人困惑的是,似乎导致解析错误的变量根本没有在 Invoke-Command 调用中使用。我的猜测是某种变量捕获正在发生,以便可以在远程执行脚本中引用变量(通过“使用”范围),这对于我的 $ArtifactDirectory 参数来说是失败的。我知道是 $ArtifactDirectory 参数导致了问题,只是因为异常中“正则表达式”的值是 $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()]
【问题讨论】:
-
我想看看你如何用
$ArtifactDirectory制作$someFancyCommand的例子?如果您实际运行上面列出的命令,我想错误会有所不同。还有为什么invoke-expression?为什么不只是-Command? -
$ArtifactDirectory 根本没有用于 $someFancyCommand。 $ArtifactDirectory 在 Invoke-Command 调用之后很久就在 MyScript.ps1 的其他地方使用。正在执行的表达式基本上是一个 TopShelf 命令行来启动/停止/安装等 Windows 服务。表达式本身看起来像“& 'c:\myapp\host.exe' start”。正如我在帖子中提到的,命令本身似乎并不重要——我可以用一个根本不使用变量的简单 Write-Host 替换它,但它仍然失败。当你说“为什么不只是 -Command”时,你指的是什么?
-
如果错误与
$ArtifactDirectory相关,那么为什么我们没有看到它在使用中(如果错误来自 PowerShell)?我以为它们是相关的,并且您只是在运行一些 exe,所以我质疑您对 IEX 的使用。Invoke-Command -Command在这种情况下也可以正常工作......我再次试图弄清楚变量与您的代码的关系。我对 TFS 一无所知,所以这可能只是我的无知。错误是否来自 TFS 发布管理? -
抱歉 - 我知道它是 $ArtifactDirectory 变量,只是因为异常中的值(那个长文件夹路径)是 $ArtifactDirectory 参数中的值。 TFS 代理在发布期间确实记录了该错误。有趣的是,如果我手动运行它,这不会发生。我将相应地更新问题 - 它必须与 MS Agent 如何执行 powershell 脚本有关。
标签: powershell release-management tfs-2015