PowerShellのGet-ADUser繰り返し処理を高速化


背景

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桁のレベルで高速化します。

以上