У меня есть простой скрипт, который генерирует отчет о сиротах OneDrive. Он работает, но очень медленно, поэтому мне просто интересно, как я могу изменить свой скрипт, чтобы ускорить процесс. Любая помощь или предложение будут очень признательны.
В основном это то, что я делаю:
$ImportData = "E:\scripts\AllOneDriveUser.csv"
$Report = "E:\scripts\OrphanOneDrive.csv"
$CSVImport = Import-CSV $ImportData
ForEach ($CSVLine in $CSVImport) {
$CSVOwner = $CSVLine.Owner
try{
Get-AzureADUser -ObjectId $CSVOwner
}catch{
$StatusMessage = $_.Exception.Message
if ($Null -eq $StatusMessage){
Write-Host "User Found, Ignore from orphan list."
}else{
#Owner not found in AzureAD
$group = 'TargetGroup'
$filter = '(memberof = {0})' -f (Get-ADGroup $group).DistinguishedName
$filterName = Get-ADUser -LDAPFilter $filter
$ModifiedOwner = $CSVOwner -split"@"[0]
if ( $ModifiedOwner[0] -in $filterName.Name ){
Write-host "Adding it into orphaned list"
$CSVLine | Export-Csv $Report -Append -notypeinformation -force
}else{
Write-Host "Not orphaned"
}
}
}
}
У меня есть более 8000 записей в моем CSV-файле импорта и более 5000 участников в моей локальной группе AD, поэтому это занимает очень много времени.
@santiagoSquarzon Хорошо, я исправил это сейчас, не могли бы вы проверить это для меня еще раз. Я также только что понял, что мне может не понадобиться выполнять поиск AzureADUser. Я просто мог бы проверить владельца из CSV с членами onPrem ADGroup.
Я не уверен, что это ускорит процесс намного быстрее.
мм, вы все еще можете сделать это, запросив AzureAD, это зависит от вас, но для ускорения вашего кода я опубликую ответ, но мне нужно подтвердить, что такое $CSVLine.Owner
? это основное имя пользователя или почтовый адрес? Обратите внимание, что они могут быть разными, и важно знать, с каким из них мы имеем дело.
Это имя участника-пользователя. что-то вроде этого [email protected]
Да, я думаю, мне определенно нужно вернуть запрос Azure AD.
Хорошо, отредактируйте свой вопрос, и я опубликую ответ через несколько. Можете ли вы подтвердить использование модуля AzureAD, если это работает? Get-AzureADUser -Filter "userprincipalname eq '[email protected]'"
? используя действительный userprincipalname
конечно
Хорошо .. Я добавил все обратно, и да, эта команда работает. Он возвращает мою информацию.
Вы можете значительно улучшить свой скрипт, используя HashSet<T> в этом случае, но также основная проблема вашего кода заключается в том, что вы запрашиваете одну и ту же группу снова и снова, это должно быть вне цикла!
Также используется Export-Csv -Append
, добавление к файлу на итерацию цикла очень медленное, лучше упростить процесс с помощью конвейеров, поэтому Export-Csv получает объекты и экспортирует только один раз вместо открытия и закрытия FileStream каждый раз.
Надеюсь, встроенные комментарии объяснят логику, которой вы можете следовать, чтобы улучшить его.
$ImportData = "E:\scripts\AllOneDriveUser.csv"
$Report = "E:\scripts\OrphanOneDrive.csv"
# we only need to query this once! outside the try \ catch
# a HashSet<T> enables for faster lookups,
# much faster than `-in` or `-contains`
$filter = '(memberof = {0})' -f (Get-ADGroup 'GroupName').DistinguishedName
$members = [Collections.Generic.HashSet[string]]::new(
[string[]] (Get-ADUser -LDAPFilter $filter).UserPrincipalName,
[System.StringComparer]::OrdinalIgnoreCase
)
Import-CSV $ImportData | ForEach-Object {
# hitting multiple times a `catch` block is expensive,
# better use `-Filter` here and an `if` condition
$CSVOwner = $_.Owner
if (Get-AzureADUser -Filter "userprincipalname eq '$CSVOwner'") {
# we know this user exists in Azure, so go next user
return
}
# here is for user not found in Azure
# no need to split the UserPrincipalName, HashSet already has
# a unique list of UserPrincipalNames
if ($hash.Contains($CSVOwner)) {
# here is if the UPN exists as member of AD Group
# so output this line
$_
}
} | Export-Csv $Report -NoTypeInformation
Большое спасибо за вашу помощь еще раз. Это работает, и это действительно намного быстрее. :)
Есть пара проблем: во-первых, вам не нужно запрашивать одну и ту же группу и получать членство в группе каждый раз, когда вы нажимаете на блок
catch
, другими словами,$filterName = Get-ADUser -LDAPFilter $filter
и$filter = '(memberof = {0})' -f (Get-ADGroup 'GroupName').DistinguishedName
должны быть внеtry
/catch
. Другая проблема заключается в сравнении$CSVOwner -eq $filterName.Name
.$CSVOwner
потенциально является адресом электронной почты, а$filterName.Name
представляет собой массив атрибутов пользователейName
, так что сравнение каждый раз будет завершаться ошибкой. Вы также хотите использовать-in
вместо-eq
там