Как я могу писать отладочные сообщения на консоль и выполнять свой код (отладку) при использовании `ForEach-Object -AsJob -Parallel...`?

Я оптимизировал свой код для повышения производительности, используя 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)
  }
}

Убедитесь, что настройка подробного вывода не подавляет подробный вывод изнутри параллельного блока, тогда ... |Receive-Job -Verbose

Mathias R. Jessen 02.09.2024 20:13

После запуска введите скрипт: $applicationPermissions и $applicationPermissions.Count, чтобы проверить, есть ли какие-либо данные. Хост записи должен возвращать данные. Скорее всего, $applicationPermission не имеет нулевого значения, но не содержит перечисляемого массива. поэтому код не проходит через foreach.

jdweng 02.09.2024 20:25

Кстати: вы говорите об отладочных сообщениях, тогда как используете Write-Verbose . PowerShell имеет отдельные потоки вывода для отладочных и подробных сообщений, причем сообщения отладки создаются с помощью Write-Debug. Тем не менее, рассматриваемая проблема относится к обоим этим потокам.

mklement0 02.09.2024 23:52

@jdweng - это не имеет особого смысла. $applicationPermissions не $null и содержит данные

Shuzheng 03.09.2024 08:29
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
59
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  • Как правило, командлеты, которые принимают блоки сценариев , ожидают, что эти блоки сценариев будут сами управлять выводом своего потока, а вызывающему объекту необходимо использовать перенаправления для захвата или подавления такого вывода.

    • Таким образом, если вывод заданного потока , такого как подробный поток в рассматриваемом случае, не включен внутри блока сценария, он не будет отображаться в контексте вызывающего объекта.

    • Следовательно, чтобы отобразить вывод подробного потока, вы должны либо использовать вызовы Write-Verbose -Verbose ... внутри блока скрипта (т. е. используя общий параметр -Verbose), либо установить $VerbosePreference = 'Continue' в начале блока.

  • Однако из-за предполагаемой ошибки, начиная с PowerShell (Core) 7.4.x, вывод из параллелизма на основе потоков - как через ForEach-Object -Parallel (с -AsJob или без него), так и Start-ThreadJob - неожиданно дополнительно фильтруется настройками управления потоком вызывающей стороны (с помощью общих параметров или эквивалентных переменных предпочтений).


Вот минимальные примеры, которые обеспечивают обходной путь:

# !! 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

Спасибо, @mklement0. Вы говорите, что вызывающему абоненту необходимо использовать перенаправления для захвата или подавления такого вывода, но вы не используете перенаправления внутри своего кода?

Shuzheng 03.09.2024 08:34

Вам нужно, как я могу отладить этот код, т. е. пройти через него, как в других языках программирования?

Shuzheng 03.09.2024 08:35

Есть ли преимущество использования Receive-Job перед Wait-Job? Зачем это нужно -AutoRemoveJob?

Shuzheng 03.09.2024 08:36

@Shuzheng: Перенаправления: это была общая информация, которая не применима к вашему варианту использования, учитывая, что (а) вы просто хотите распечатать информацию на дисплее и (б) перенаправления в целом применяются только к фактическому выводу потока, тогда как ваша проблема в его отсутствии из-за того, что вы не включили подробный поток в источнике.

mklement0 03.09.2024 12:33

@Shuzheng: Wait-Job просто ждет завершения задания, не получая (собирая) его выходные данные. Receive-Job, напротив, собирает выходные данные по умолчанию асинхронно; если вы добавите -Wait, сначала ожидается завершение задания, а -AutoRemoveJob после этого автоматически удаляет задание. Этот метод полезен для автономных фрагментов кода, демонстрирующих, что выводит данное задание.

mklement0 03.09.2024 12:40

Спасибо за помощь! Я создам новый вопрос, если вы настаиваете и верите, что у вас есть ответ :)

Shuzheng 05.09.2024 19:51

С удовольствием, @Shuzheng; Я не осознавал, что вы с самого начала явно спрашивали об отладке, поэтому в конце концов нет необходимости создавать новый вопрос. Я скоро обновлю этот ответ, но, боюсь, новости не очень хорошие.

mklement0 05.09.2024 19:53

Другие вопросы по теме