背景
PowerShellのGet-ADUserコマンドレットをつかって、Active Directoryから数千件以上の単位でユーザオブジェクトを取得後、ユーザの属性を使って繰り返し処理をすると、非常に遅くなります。
例えばこんな感じです。
Sample01.ps1
$users = Get-ADUser -Server MyADServer01:3268 -Filter { enabled -eq $true } -Properties SAMAccountName,mail,department,lastLogonDate
foreach ($user in $users) {
if ($user.lastLogonDate -lt (Get-Date).AddMonths(-6)) {
# 何かの処理
}
}
繰り返し処理内部の各ユーザのプロパティーは、どうやらそのつどActive Directoryへ問合せが発生するようで、パイプラインを使っても速度は改善されません。
SearchBaseオプションで検索対象のOUを限定しても、戻り値のユーザ数を大幅に減らさない限り処理速度は大きく変わりません。
また、いったん連想配列に代入しても、メモリ上にキャッシュしてくれるわけではないようで、やはり問題は解決しません。
StackOverflowにもこの質問はいくつか見つかりましたが、決定打となる回答はありませんでした。
ところが、非常にシンプルな解決法を偶然見つけました。
いったんCSVファイルに書き出すだけ
Export-CsvでGet-ADUserの結果をいったんCSVファイルに書出し、Import-Csvで連想配列に読み込みましょう。
Sample02.ps1
Get-ADUser -Server MyADServer01:3268 -Filter { enabled -eq $true } -Properties SAMAccountName,mail,department,lastLogonDate |
Export-Csv -Path .\temp.csv -Delimiter "," -Encoding UTF8 -Force
$users = Import-Csv Path .\temp.csv -Delimiter "," -Encoding UTF8
Remove-Item -Path .\temp.csv
これだけでメモリにキャッシュしてくれるようで、繰り返し処理が場合によっては2桁のレベルで高速化します。
以上