使用 `ForEach-Object -AsJob -Parallel ...` 时,如何将调试消息写入控制台并单步执行代码(调试)?

问题描述 投票:0回答:1

我利用

ForEach-Object -AsJob -Parallel ...
优化了代码的性能。

但是,它有一个重大缺点,因为我无法将调试消息写入控制台,也无法通过单步执行来调试我的代码。

因此,每次我想调试代码时,我都必须删除

-AsJob
-Parallel
选项,然后例如添加调试日志记录语句,这是我想避免的(!)。我不明白这个规模如何 - 如果每个循环有数百个并行,所有这些都看起来像“黑匣子”,会怎么样。

使用

ForEach-Object -AsJob -Parallel ...
时,如何将调试消息写入控制台并单步执行代码?

$appPermissionsJob = $servicePrincipals | ForEach-Object -AsJob -ThrottleLimit $ThrottleLimit -Parallel {
  $spApplicationPermissions = $using:spApplicationPermissions
  $servicePrincipalId = $_.Id

  try {
    $applicationPermissions = Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $servicePrincipalId -All -PageSize 999

    if ($applicationPermissions -ne $null) {
      $applicationPermissions | ForEach-Object {
        Write-Host "Processing service principal ${servicePrincipalId} with app role $($_.ResourceId)"
        if ($_.ResourceId -eq $using:MSGraphServicePrincipalId) {
          $item = New-Object PSObject -Property ([ordered] @{
              ServicePrincipalId     = $_
              ApplicationPermissions = $applicationPermissions
            })
          $spApplicationPermissions.TryAdd($servicePrincipalId, $item)
        }
      }
    }
  }
  catch {
    Write-Verbose "Failed to download delegated permissions for service principal ${servicePrincipalId}: $($_.Exception.Message)"
    $dictFailed.TryAdd($servicePrincipalId, $_.Exception.Message)
  }
}
powershell debugging verbose
1个回答
0
投票
  • 通常,接受脚本块的 cmdlet 期望这些脚本块能够控制其流输出本身,调用者需要使用重定向才能捕获或抑制此类输出。

    • 因此,除非给定的输出(例如本例中的verbose流),在脚本块内打开,否则它不会在调用者的上下文中出现 .

    • 因此,为了显示详细流输出,您必须在脚本块内使用

      Write-Verbose -Verbose ...

       调用(即使用通用 
      -Verbose
       参数),或者在块的开头设置 
      $VerbosePreference = 'Continue'

  • 但是,由于

    假定的 bug,从 PowerShell (Core) 7.4.x 开始,基于线程的并行性的输出 - 均通过 ForEach-Object -Parallel

    (有或没有 -AsJob
    )并且 
    Start-ThreadJob
     - 由
    调用者流控制设置出乎意料地额外过滤(无论是通过通用参数还是等效的偏好变量)。

      请参阅
    • GitHub 问题 #24016

以下是最小的示例:

# !! The *outer* -Verbose arguably shouldn't be necessary in either case, # !! but is, as of PowerShell 7.4.x ForEach-Object -Parallel { Write-Verbose hi -Verbose } -Verbose ForEach-Object -AsJob -Parallel { Write-Verbose hi -Verbose } | Receive-Job -Wait -AutoRemoveJob -Verbose
    
© www.soinside.com 2019 - 2024. All rights reserved.