【问题标题】:Powershell Invoke-Command resulting in RegEx errorPowershell Invoke-Command 导致 RegEx 错误
【发布时间】: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


【解决方案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

无论如何,我将上述脚本重构为一个模块/函数,问题就完全消失了。

【讨论】:

    【解决方案2】:

    我试过了,它适用于普通的 PowerShell。正如您在问题中指出的那样,这绝对似乎是 TFS 发布管理问题,它是对输入参数的处理。

    解决方案/解决方法:请尝试转义路径 "C:\MSAgent\_work\66f1e4ebb\Cc - (WIP)\CC - My Cool App" 中的所有特殊字符。 PowerShell 中的转义序列是字符 \

    为方便起见,这里是路径与转义序列的样子:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-12-02
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 2021-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多