PowerShellで最終ログオン日一覧を作るなら、最短ルートは Get-ADUser -Filter * -Properties LastLogonDate で AD ユーザーを取得し、Export-Csv で一覧化する方法です。まずここから始めれば、棚卸しや定期レポートはかなり楽になります。
ただし、LastLogonDate は PowerShell の AD オブジェクトが持つ派生プロパティで、元は lastLogonTimestamp です。手軽に一覧化するには向きますが、退職者の停止判断や監査のように厳密な時刻が必要な場面では、全ドメイン コントローラーの lastLogon を集計する必要があります。この記事では、すぐ使える基本スクリプトから、OU 単位の絞り込み、CSV 出力、失敗しやすい点、精度が必要な場合の代替策まで、迷わず進められる形で整理します。 (Microsoft Learn)
PowerShellで最終ログオン日一覧を作るなら、まずこの形
オンプレミスの Active Directory で、まず一覧を作りたいだけなら、Get-ADUser に LastLogonDate を追加プロパティとして指定して取得するのがいちばん扱いやすい方法です。Get-ADUser は複数ユーザーの検索に使え、既定では限られたプロパティしか返さないため、LastLogonDate のような追加項目は -Properties で明示します。 (Microsoft Learn)
まずは画面で確認する
Import-Module ActiveDirectory
Get-ADUser -Filter * -Properties DisplayName, Enabled, LastLogonDate |
Select-Object SamAccountName, DisplayName, Enabled, LastLogonDate |
Sort-Object LastLogonDate -Descending
最初は CSV にせず、コンソールで数件だけ確認するのがおすすめです。意図したユーザーが出るか、日付が空欄のアカウントが混ざっていないかを先に見ておくと、後の手戻りが減ります。
CSVで保存する
Import-Module ActiveDirectory
New-Item -ItemType Directory -Path 'C:\Temp' -Force | Out-Null
Get-ADUser -Filter * -Properties DisplayName, Enabled, LastLogonDate |
Select-Object SamAccountName, DisplayName, Enabled, LastLogonDate, DistinguishedName |
Sort-Object LastLogonDate -Descending |
Export-Csv -Path 'C:\Temp\AD-LastLogonDate.csv' -NoTypeInformation -Encoding UTF8
Export-Csv は区切り文字やエンコードを指定できます。-NoTypeInformation は #TYPE 行を消すための定番指定です。Excel で開いたときに列が崩れる環境では、後述の -UseCulture を使うと改善しやすくなります。 (Microsoft Learn)
先に理解したい LastLogonDate と lastLogon の違い
最終ログオン関連で混同しやすいのは、LastLogonDate、lastLogonTimestamp、lastLogon の3つです。LastLogonDate は PowerShell 側の派生プロパティで、元は lastLogonTimestamp です。lastLogonTimestamp は DC 間で複製される一方、更新はリアルタイムではなく、更新タイミングは msDS-LogonTimeSyncInterval の影響を受けます。lastLogon は DC ごとに別管理され、正確な値を出すには全 DC を見て最大値を採る必要があります。 (Microsoft Learn)
| 項目 | 向いている用途 | 注意点 |
|---|---|---|
LastLogonDate | 日常の一覧作成、CSVレポート | 手軽だが厳密な最終ログオン時刻ではない |
lastLogonTimestamp | 非アクティブ候補の把握 | 更新遅延があり、即時反映を期待しにくい |
lastLogon | 監査、無効化前の最終確認 | 全 DC 照会が必要で、件数が多いと重い |
迷ったら、一覧作成は LastLogonDate、削除や停止の判断前チェックは lastLogon と覚えておくと外しにくいです。 (Microsoft Learn)
実行前の前提条件
この記事の手順は、オンプレミスの Active Directory Domain Services を前提にしています。Microsoft Learn では、Active Directory モジュールは AD DS / AD LDS を管理するためのモジュールとして案内されており、読み込みは Import-Module ActiveDirectory で行えます。Windows クライアントでは RSAT を機能として追加し、Windows 11 は Pro / Enterprise エディションが前提です。Windows Server では Install-WindowsFeature で AD 関連ツールを導入できます。 (Microsoft Learn)
Windowsクライアントで準備する
Get-WindowsCapability -Online | Where-Object Name -like 'RSAT*'
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0
Import-Module ActiveDirectory
Windows Serverで準備する
Install-WindowsFeature -Name RSAT-AD-Tools -IncludeAllSubFeature
Import-Module ActiveDirectory
Get-ADUser が見つからないときは、まず RSAT と ActiveDirectory モジュールを疑うのが近道です。PowerShell を開き直しても解決しない場合は、Get-Module -ListAvailable ActiveDirectory で存在確認をすると切り分けが早くなります。
よく使う絞り込みパターン
Get-ADUser は -Filter で条件を付けられ、-SearchBase で検索範囲の AD パスを絞れます。SearchBase には OU 名だけではなく、OU=Users,DC=example,DC=com のような DN 形式を入れるのがポイントです。 (Microsoft Learn)
有効ユーザーだけに絞る
Get-ADUser -Filter { Enabled -eq $true } -Properties DisplayName, LastLogonDate |
Select-Object SamAccountName, DisplayName, LastLogonDate |
Sort-Object LastLogonDate -Descending
無効化済みユーザーを除いて、運用中アカウントだけを見たいときに向いています。定期レポートは、まずこの形から始めるとノイズが減ります。
特定OUだけを対象にする
$searchBase = 'OU=Users,OU=Tokyo,DC=example,DC=com'
Get-ADUser -Filter { Enabled -eq $true } -SearchBase $searchBase -Properties DisplayName, LastLogonDate |
Select-Object SamAccountName, DisplayName, LastLogonDate |
Sort-Object LastLogonDate -Descending
全ドメインを一気に回す前に、まず対象 OU だけで試すのが安全です。結果確認も速く、誤った DN を入れたときの切り分けもしやすくなります。
90日以上ログオンがない候補を出す
$threshold = (Get-Date).AddDays(-90)
Get-ADUser -Filter { Enabled -eq $true } -Properties DisplayName, LastLogonDate |
Where-Object { -not $_.LastLogonDate -or $_.LastLogonDate -lt $threshold } |
Select-Object SamAccountName, DisplayName, LastLogonDate |
Sort-Object LastLogonDate
この形なら、90日以上前のユーザーだけでなく、LastLogonDate が入っていないアカウントも一緒に拾えます。新規作成だけされて未使用のアカウントを見落としたくないときに便利です。
非アクティブ候補の抽出が目的なら、Search-ADAccount -AccountInactive -UsersOnly -TimeSpan (New-TimeSpan -Days 90) も使えます。こちらは期間指定のための専用コマンドで、TimeSpan または DateTime を使って閾値を指定できます。ただし、一覧レポートとして列を整えたいときは Get-ADUser ベースの方が扱いやすいです。なお、この判定は Windows Server 2003 のドメイン機能レベル以上が前提です。 (Microsoft Learn)
正確な最終ログオン時刻が必要なときは、全DCの lastLogon を集計する
lastLogon は複製されない属性なので、ドメイン内の正確な最終ログオンを知りたい場合は、各ドメイン コントローラーから取得して最大値を使う必要があります。DC 一覧の取得には Get-ADDomainController を使えます。つまり、無効化や削除の最終判断に使うレポートは、LastLogonDate の簡易一覧ではなく、この方法で別取りするのが安全です。 (Microsoft Learn)
Import-Module ActiveDirectory
$searchBase = 'OU=Users,OU=Tokyo,DC=example,DC=com'
$dcs = Get-ADDomainController -Filter *
$latest = @{}
foreach ($dc in $dcs) {
try {
$users = Get-ADUser -Server $dc.HostName -SearchBase $searchBase -Filter * -Properties DisplayName, Enabled, lastLogon
foreach ($user in $users) {
if (-not $user.Enabled) { continue }
$key = $user.ObjectGUID.ToString()
$raw = [int64]$user.lastLogon
if (-not $latest.ContainsKey($key) -or $raw -gt $latest[$key].LastLogonRaw) {
$latest[$key] = [pscustomobject]@{
SamAccountName = $user.SamAccountName
DisplayName = $user.DisplayName
LastLogon = if ($raw -gt 0) { [datetime]::FromFileTime($raw) } else { $null }
SourceDC = $dc.HostName
LastLogonRaw = $raw
}
}
}
}
catch {
Write-Warning "$($dc.HostName) の取得に失敗しました: $($_.Exception.Message)"
}
}
New-Item -ItemType Directory -Path 'C:\Temp' -Force | Out-Null
$latest.Values |
Select-Object SamAccountName, DisplayName, LastLogon, SourceDC |
Sort-Object LastLogon -Descending |
Export-Csv -Path 'C:\Temp\AD-ExactLastLogon.csv' -NoTypeInformation -Encoding UTF8
このスクリプトは実務向きですが、負荷はそれなりにあります。いきなり全ドメインで回すのではなく、まず 1 OU か、停止候補だけに絞って実行した方が現実的です。
月次レポートまでこれで回す必要はほとんどありません。普段は LastLogonDate、判断の最終段階だけ lastLogon に切り替える運用がバランスを取りやすいです。
失敗しやすいポイントと対処
つまずきやすいのは、モジュール未導入、属性の取り違え、CSV の区切り文字、検索範囲の広げすぎです。特に LastLogonDate と lastLogon を同じ意味で扱うと、レポートは作れても判断を誤りやすくなります。Export-Csv は -UseCulture で現在のカルチャの区切り文字を使えるので、Excel で1列に見えるときはまずここを疑うと早いです。 (Microsoft Learn)
| 症状 | よくある原因 | まずやること |
|---|---|---|
Get-ADUser が使えない | RSAT / ActiveDirectory モジュールが未準備 | RSAT を入れて Import-Module ActiveDirectory |
| GUIや別レポートと日付が合わない | LastLogonDate と lastLogon を混同している | 目的に応じて属性を使い分ける |
| CSVをExcelで開くと1列になる | 区切り文字がロケールと合っていない | Export-Csv -UseCulture を付ける |
| 全件取得が重い | いきなり全ドメインを対象にしている | -SearchBase で OU 単位に分ける |
CSV が崩れる環境では、出力行を次のように変えるだけで改善することがあります。
Export-Csv -Path 'C:\Temp\AD-LastLogonDate.csv' -NoTypeInformation -Encoding UTF8 -UseCulture
戻し方と代替策
この記事で使っている Get-ADUser、Get-ADDomainController、Search-ADAccount、Export-Csv は、一覧取得と出力が中心です。AD オブジェクト自体を書き換えないので、基本的に「戻し方」は不要です。不要になった CSV を削除すれば十分です。
代替策の選び方は、次の3つで考えると迷いません。
| 目的 | 選ぶ方法 |
|---|---|
| まず一覧を作りたい | Get-ADUser + LastLogonDate |
| 長期間未使用の候補を洗い出したい | Search-ADAccount -AccountInactive |
| 正確な最終ログオンを確認したい | 全 DC の lastLogon を集計 |
Search-ADAccount -AccountInactive は期間指定の専用手段として便利ですが、厳密な最終ログオン時刻そのものを保証する用途ではありません。停止や削除の前には、必要な範囲だけでも lastLogon を取り直す方が安全です。 (Microsoft Learn)
迷ったらこの順番で進める
- まずは
Get-ADUser+LastLogonDateで、対象 OU の一覧を小さく出す - 問題なければ CSV 出力に切り替える
- 停止候補や削除候補だけを抽出する
- 実際に無効化する前に、その候補だけ全 DC の
lastLogonで再確認する
PowerShellで最終ログオン日一覧を作る作業は、最初から完璧な精度を狙うより、一覧作成と最終確認を分ける 方が運用しやすくなります。
日常業務のレポートは LastLogonDate、判断が重い場面だけ lastLogon。この切り分けにしておくと、速さと正確さの両方を無理なく両立できます。

コメント