Powershell Return-Job иногда возвращает пустые значения - PullRequest
0 голосов
/ 12 апреля 2020

Я использую сценарий Powershell для параллельной проверки состояния нескольких сборок TFS через API-интерфейсы Start-Job.

Кажется, все работает нормально, но если я отменю сборки сразу после их запуска off-Receive-Job, похоже, возвращает null, несмотря на то, что задачи выполнены.

Это код, выполняющий роль привратника:

While (@(Get-Job | Where { $_.State -eq "Running" }).Count -ne 0)
{
    ForEach ($Job in (Get-Job)) {
       $currentJobOutput = Receive-Job $job 6>&1  
    }
   Start-Sleep -Seconds $buildCheckingIntervalInSeconds
}

$jobsReturnData = @()
ForEach ($Job in (Get-Job)) {
Write-Host $job.State
    Wait-Job $job | out-null
   $hastBaleResult = Receive-Job $Job -Wait:$true;
   $jobsReturnData += New-Object PSObject -property $hastBaleResult
   Remove-Job $Job
}

Write-Host "`n`nBuilds recap`n"
Write-Host "Build Definition Name".PadRight(29,' ')"Build Status".PadRight(14,' ')"Build Execution URL"
$hasAnyBuildFailed=$false;

foreach($jobReturnData in $jobsReturnData)
{
Write-Host "JobReturnedData"$jobReturnData
    $currentForegroundColor="White";
    switch($jobReturnData.buildStatus){
        "succeeded" {$currentForegroundColor="Green"; break}
        "partiallySucceeded" {$currentForegroundColor="Yellow"; break}
        "failed" {$currentForegroundColor="Red"; break}
        "canceled" {$currentForegroundColor="Red"; break}
    }

    Write-Host -ForegroundColor $currentForegroundColor "$($jobReturnData.buildDefinitionName.PadRight(30,' '))$($jobReturnData.buildStatus.PadRight(15,' '))$($jobReturnData.buildUrl)"
    if(($jobReturnData.buildStatus -eq "failed") -or ($jobReturnData.buildStatus -eq "canceled")){
        $hasAnyBuildFailed = $true;
    }
}

if($hasAnyBuildFailed){
    throw "Not all builds completed successfully";
}

Большую часть времени он работает нормально, но как Как указано выше, при некоторых обстоятельствах вывод, который я получаю,

Completed
Completed
Pull Request - Full Build      - ExecID=247764 - Build Status: canceled        - You can access the build execution at myTfs/_build/index?buildId=247764&_a=summary
DeleteMe:Returning System.Collections.DictionaryEntry System.Collections.DictionaryEntry System.Collections.DictionaryEntry


Builds recap

Build Definition Name         Build Status   Build Execution URL
JobReturnedData 
You cannot call a method on a null-valued expression.
At myScript.ps1:377 char:60
+ ... undColor "$($jobReturnData.buildDefinitionName.PadRight(30,' '))$($jo ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

You cannot call a method on a null-valued expression.
At myScript.ps1:377 char:114
+ ... adRight(30,' '))$($jobReturnData.buildStatus.PadRight(15,' '))$($jobR ...
+                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull


JobReturnedData @{buildStatus=canceled; buildDefinitionName=Pull Request - Full Build; buildUrl=myTfs/_build/index?buildI
d=247764&_a=summary}
Pull Request - Full Build     canceled       myTfs/_build/index?buildId=247764&_a=summary
Not all builds completed successfully
At myScript.ps1:384 char:5
+     throw "Not all builds completed successfully";
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (Not all builds completed successfully:String) [], RuntimeException
    + FullyQualifiedErrorId : Not all builds completed successfully

С чем это связано?

1 Ответ

0 голосов
/ 13 апреля 2020

Я закончил хранить заданные в очереди задания в массиве и перебирать их.

$jobsReturnData = @()
While (@($jobs | Where { $_.State -eq "Running" }).Count -ne 0) {

    #Redirect the transient output from each job to the main output window
    ForEach ($job in @($jobs | Where { $_.State -eq "Running" })) {
        $currentJobOutput = Receive-Job $job 6>&1
        if($job.HasMoreData){
            Wait-Job $Job -Timeout $buildCheckingIntervalInSeconds
        }
    }
    #Get return values from each completedjob without waiting for all jobs to finish
    ForEach ($job in @($jobs | Where { ($_.State -eq "Completed")})) {
        $jobReturnData = Receive-Job $Job -Wait:$true;
        $jobsReturnData += New-Object PSObject -property $jobReturnData
        Remove-Job $Job
        $jobs[[array]::IndexOf($jobs, $Job)] = $null
    }


    Start-Sleep -Seconds $buildCheckingIntervalInSeconds
}

#Get return values from each completedjob
ForEach ($job in @($jobs | Where { ($_.State -eq "Completed")})) {
    $jobReturnData = Receive-Job $Job -Wait:$true;
    $jobsReturnData += New-Object PSObject -property $jobReturnData
    Remove-Job $Job
    $jobs[[array]::IndexOf($jobs, $Job)] = $null
}

Я заметил, что иногда задание завершается, но работает до тех пор, пока на нем не будет выполнено ожидание, что довольно озадачивает.

Я добавил две проверки для получения возвращаемых значений из выполненных заданий, чтобы не пришлось ждать завершения всех из них перед отображением обновления на экране.

...