#powershell #parallel-processing #microsoft-graph-api #office365
#powershell #параллельная обработка #microsoft-graph-api #office365
Вопрос:
У меня есть некоторый рабочий код, который в основном запрашивает 2 разные конечные точки Graph API, затем ищет совпадение в User Principal Name column
, и вставляет extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber
столбец и значения в экспортированный csv (спасибо пользователю @PMental за это решение) Этот столбец является производным от атрибута, который был недавно расширен из нашего локального AD.
Этот код работает отлично, однако, если я попытаюсь его распараллелить, я не получу результатов в extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber
столбце.
Это потому, что после распараллеливания я не могу обмениваться переменными между параллельными процессами? Если да, то как мне это сделать?
Приведенный ниже код — если вы удалите -Parallel, он работает нормально:
$graphApiUri = "https://graph.microsoft.com/v1.0/reports/getOffice365ActiveUserDetail(period='D90')"
$Uri = "https://graph.microsoft.com/v1.0/users?`$select=userPrincipalName,extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber"
$O365Report = Invoke-RestMethod -Method Get -Uri $graphApiUri -Headers $headerParams | ConvertFrom-Csv
# If the result is more than 999, we need to read the @odata.nextLink to show more than one side of users
$UserDetails = while (-not [string]::IsNullOrEmpty($uri)) {
# API Call
$apiCall = try {
Invoke-RestMethod -Headers $headerParams -Uri $uri -Method Get
}
catch {
$errorMessage = $_.ErrorDetails.Message | ConvertFrom-Json
}
$uri = $null
if ($apiCall) {
# Check if any data is left
$uri = $apiCall.'@odata.nextLink'
$apiCall
}
}
Write-Output "Matching UPN to employeeNumber..."
$O365Report | ForEach-Object -Parallel {
$CurrentEmpNumber = $UserDetails.value |
Where-Object userPrincipalName -eq $_.'User Principal Name' |
Select-Object -ExpandProperty extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber -ErrorAction SilentlyContinue
$_ | Add-Member -MemberType NoteProperty -Name extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber -Value $CurrentEmpNumber
}
$O365Report | Export-Csv $ReportCSV -NoTypeInformation
Write-Output "Report saved to $ReportCSV."
Комментарии:
1. Это не похоже на хорошее соответствие для параллельной обработки, поскольку вы просто локально просматриваете массивы в поисках совпадений. Если у вас не было результатов 500K и время не имело значения, ИМХО, это не имеет смысла. Теперь, если вам нужно было выполнить еще один вызов rest для каждого пользователя, возможно, стоит приложить усилия для этого.
2. Я ценю вашу проницательность! Спасибо
Ответ №1:
Когда вы находитесь внутри ForEach-Object -Parallel
блока сценария и пытаетесь ссылаться на переменные, которые были созданы вне его, вам нужно предварить имя переменной using:
, чтобы оно было $using:UserDetails
Примеры:
Ничего не возвращает, поскольку $test
недоступен в пределах блока параллельного скрипта:
$test = 1;
0..5 | % -Parallel { $test; };
Возвращает значение $test
в пять раз, потому что с помощью $using:test
теперь вы можете видеть его значение:
$test = 1;
0..5 | % -Parallel { $using:test; };
Из документации:
Набор параметров ForEach-Object -Parallel запускает блоки сценариев параллельно в отдельных потоках процесса. Ключевое слово $using: позволяет передавать ссылки на переменные из потока вызова командлета в каждый поток запущенного блока сценария. Поскольку блоки сценария выполняются в разных потоках, переменные объекта, передаваемые по ссылке, должны использоваться безопасно. Как правило, безопасно читать из объектов, на которые ссылаются, которые не меняются. Но если состояние объекта изменяется, вы должны использовать потокобезопасные объекты, такие как .Net System.Коллекция.Параллельные типы (см. Пример 11).
Личное замечание:
Я бы также рекомендовал использовать -ThrottleLimit
для ограничения его максимальных степеней параллелизма. Значение по умолчанию равно 5, но в зависимости от тестирования может потребоваться больше или меньше.
Комментарии:
1. Спасибо. С другой стороны, вы случайно не знаете, поддерживается ли функция -Parallel в Azure runbook?
2. @jpbcx43 понятия не имею, извините.