【问题标题】:Why does PowerShell intermittently not find List[string].Add() method?为什么 PowerShell 间歇性找不到 List[string].Add() 方法?
【发布时间】:2015-11-22 12:34:36
【问题描述】:

我有一个构建脚本(Windows 2012 R2 上的 PowerShell 4),它在后台作业中运行 NUnit 并返回 NUnit 的输出。此输出收集在 Collections.Generic.List[string] 中。

$nunitJob = Start-Job -ScriptBlock { 
                                    param(
                                        [string]
                                        $BinRoot,

                                        [string]
                                        $NUnitConsolePath,

                                        [string[]]
                                        $NUnitParams,

                                        [string]
                                        $Verbose
                                    )

                                    Set-Location -Path $BinRoot
                                    $VerbosePreference = $Verbose

                                    Write-Verbose -Message ('{0} {1}' -f $NUnitConsolePath,($NUnitParams -join ' '))
                                    & $NUnitConsolePath $NUnitParams 2>&1 
                                    $LASTEXITCODE
                                 } -ArgumentList $binRoot,$nunitConsolePath,$nunitParams,$VerbosePreference

$nunitJob | Wait-Job -Timeout ($timeoutMinutes * 60) | Out-Null
$jobKilled = $false
if( $nunitJob.JobStateInfo.State -eq [Management.Automation.JobState]::Running )
{
    $jobKilled = $true
    $errMsg = 'Killing {0} tests: exceeded {1} minute timeout.' -f $assembly.Name,$timeoutMinutes
    Write-Error -Message $errMsg
}

$output = New-Object 'Collections.Generic.List[string]'

$nunitJob | 
    Stop-Job -PassThru | 
    Receive-Job |
    ForEach-Object  { 
        if( -not $_ )
        {
            [void]$output.Add( '' )
            return
        }

        switch -Regex ( $_ )
        {
            '^Tests run: (\d+), Errors: (\d+), Failures: (\d+), Inconclusive: (\d+), Time: ([\d\.]+) seconds$'
            {
                $testsRun = $Matches[1]
                $errors = $Matches[2]
                $failures = $Matches[3]
                $inconclusive = $Matches[4]
                $duration = New-Object 'TimeSpan' 0,0,$Matches[5]
                break
            }
            '^  Not run: (\d+), Invalid: (\d+), Ignored: (\d+), Skipped: (\d+)$'
            {
                $notRun = $Matches[1]
                $invalid = $Matches[2]
                $ignored = $Matches[3]
                $skipped = $Matches[4]
                break
            }
        }

        # Error happens here:
        [void] $output.Add( $_ )
    }

有时,我们的构建会因以下错误而失败:

找不到“Add”的重载和参数计数:“1”。
在行:XXXXX 字符:XXXXX
+ [无效] $output.Add( $_ )
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest

知道为什么 PowerShell 找不到 List[string]Add 方法吗?

我打开了一个控制台窗口,尝试将不同类型的对象传递给Add,而没有出现错误。

> $o = New-Object 'Collections.Generic.List[string]'
> $o.Add( '' )
> $o.Add( $null )
> $o.Add( 1 )
> $o


1

【问题讨论】:

  • 问题很可能是它无法将$_ 隐式转换为字符串。喜欢$o.Add($(New-Object psobject))
  • @zespri 我确实删除了一些行,但没有涉及$output
  • @MathiasR.Jessen 可能就是这样。我尝试了$output.Add( [pscustomobject]@{ } ) 并且能够重现该错误。现在我必须弄清楚为什么 PowerShell 不将控制台输出视为字符串。
  • “将控制台输出视为字符串”?您是否尝试在 foreach-object 期间以任何方式修改 $_?同样,整个代码块在这里可能有用/有意义。
  • 可能值得添加 Write-Verbose $_.GetType().Fullname -Verbose 以查看您正在处理的对象类型。

标签: powershell


【解决方案1】:

当您将 stderr 重定向到 stdout 时,您可以获得穿插字符串的 System.Management.Automation.ErrorRecords。当 stdout 是字符串时,Stderr 会自动转换为 ErrorRecords。

因此,您可能希望查看输出是否包含感兴趣的 ErrorRecords,如果没有,则将它们过滤掉。

【讨论】:

    猜你喜欢
    • 2011-04-15
    • 2016-12-27
    • 1970-01-01
    • 2011-03-10
    • 2013-08-20
    • 2020-08-30
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多