Active Directory 最終ログオン日時の確認

こんにちは、エス・ワイ・シー 松本です。

Active Directory には様々な有用な情報が記録・保存されていますが、たまに活用しようとして悩むことが多いのも確かです。

旧コンピューターや旧ユーザーのごみデータもしばしば残ったままになっていたりしますよね。

今も使われているかどうか確認するのに、
「最終ログオン日時」が最近ではないなら使ってないんじゃないの?
なんてすぐ思いつくアイデアではないでしょうか。

ところが Active Directory の最終ログオン日付確認には
少し紛らわしいトラップがあることを思い出したので
備忘録がてら、記載します。


こういう情報確認には、PowerShell を使います。
ドメインコントローラー上で実行すると簡単です。

Import-Module ActiveDirectory

変数に全コンピューターオブジェクト、全ユーザーオブジェクトのプロパティ全部を取得します。
対象オブジェクトが決まっている決め打ちで単体を取得しても良いです。
プロパティも必要プロパティ名を列挙すれば必要最小限取得できますが、面倒なので全部取得します。

$ADComp= Get-ADComputer -Filter * -Property *
$ADUser= Get-ADUser -Filter * -Property *



最終ログオン日時を確認するには以下のコマンドを試します。

$ADComp | FT -Property Name,LastLogonDate
$ADUser | FT -Property Name,LastLogonDate


するとどうでしょう。何やらちょっと期待した感じでない情報が列挙されます。
具体的には、確実に今日ログオンしているはずの端末、ユーザーの最終ログオン日時が
やたら古い、、、


一例を示します。
2023/1/12 に起動してログオンして利用している端末について情報表示すると
$ADComp[100] | FT -Property Name,LastLogonDate

※ 100個目のコンピューター情報を表示

name lastlogondate
—- ————-
PC01 2023/01/05 8:23:50


一応 2023/01/05 表示で新しそうですが、 操作日は 2023/1/12 なので情報としては微妙です。

Last 何とかの属性値が他に何かないか確認します。

$ADComp[100] | FT -Property Name,*Last*


すると、LastLogon、LastLogonDate、LastLogonTimeStamp というそれらしいのがあります。

注目してみてみますと以下のようになります。

$ADComp[100] | FT -Property Name,LastLogon,LastLogonDate,LastLogonTimeStamp

name LastlogOn LastLogonDate LastLogonTimeStamp
—- ——— ————- ——————
PC01 133179625587840445 2023/01/05 8:23:50 133173482307101022


LastLogonDate のみパッと見に日付スタイルなのでこれだけを信じたい、、、
他のはなんだかよくわからない・・・と思ったら失敗で、この二つもちゃんと見る必要があります。

LastLogon はいったい何時を示しているのでしょうか?
以下のコマンドで確認できます。

[DateTime]::FromFileTime($ADComp[100].LastLogon)

2023年1月12日 11:02:38

2023/1/12 を示しています。それっぽいですね。


LastLogonTimeStamp も同様に確認できます。

[DateTime]::FromFileTime($ADComp[100].LastLogonTimeStamp)

2023年1月5日 8:23:50

この例では LastLogonDate と同じ日付が記録されている模様です。


この結果だけ見ると、LastLogon の時間だけ見れば良さそうに思えるのですが、
色々調べたところ、LastLogon / LastLogonDate / LastLogonTimeStamp のうち最も新しい日付が
本当の最終ログオン日時の模様です。

この3つの値がそれぞれ異なるのは、ログオン認証に利用されたドメインコントローラー、
ドメインコントローラ間の同期処理のタイムラグなどにより発生しているものらしいです。


なるほど、最大値を求めると言えば、

[Math]::Max($ADComp[100].LastLogon,$ADComp[100].LastLogonDate,$ADComp[100].LastLogonTimeStamp)

とやりたいところですが、これはエラーになります。
Max 関数はなんとびっくり引数2つしか受け付けません・・・最大値を求めるのに引数2つってお前・・・どういう設計???
LastLogon / LastLogonTimeStamp と LastLogonDate はデータ型が違うのでこれまた比較できずエラーになります。
ぐぬぬ案件ですね、、、


Max 関数以外の最大値を出す方法のうち、ここでは Measure-Object コマンドを利用する方法を示します。

(@([DateTime]::FromFileTime($ADComp[100].LastLogon),[DateTime]::FromFileTime($ADComp[100].LastLogonTimeStamp),[DateTime]$ADComp[100].LastLogonDate) | Measure-Object -Maximum).Maximum

Count : 3
Average :
Sum :
Maximum : 2023/01/12 11:02:38
Minimum :
Property :

簡単に説明すると @(x,y,z) 配列を定義し、要素 x,y,z はそれぞれの日付情報です。
3つの値は比較可能なように [DateTime]に変換します。
Measure-Object コマンドに -Maximum を指定して最大値を求めるよう指定します。

結果、比較対象要素が3件あり、最大値が「2023/01/12 11:02:38」であることが分かりました。
これこそが本当の最終ログイン日付ということになります。

・・・しかしまぁ、なんですよ。日付だけ知り合いので合って、要素数とかどうでもいいわけですよ。
こんな時も PowerShell なので、全体を () で括り、Maximum 参照してやれば、、、

(@([DateTime]::FromFileTime($ADComp[100].LastLogon),[DateTime]::FromFileTime($ADComp[100].LastLogonTimeStamp),[DateTime]$ADComp[100].LastLogonDate) | Measure-Object -Maximum).Maximum

2023年1月12日 11:02:38


結果、3項目からの最大値こそが最新のログオン情報。


後は全体の一覧と最終ログオン日時が列挙されれば勝利確定。


$ADComp | Select-Object -Property Enabled,Name,CanonicalName,OperatingSystem,
@{Name=”FinalLogon”;Expression={
(@([DateTime]::FromFileTime($_.LastLogon),[DateTime]::FromFileTime($_.LastLogonTimeStamp),[DateTime]$_.LastLogonDate) | Measure-Object -Maximum).Maximum
}} | FT -AutoSize



$ADUser | Select-Object -Property Enabled,Name,CanonicalName,samAccountName,
@{Name=”FinalLogon”;Expression={
(@([DateTime]::FromFileTime($_.LastLogon),[DateTime]::FromFileTime($_.LastLogonTimeStamp),[DateTime]$_.LastLogonDate) | Measure-Object -Maximum).Maximum
}} | FT -AutoSize


え?「画面に出ても仕方ないのだけれど?」
それはおっしゃる通り。 CSV で保存すれば大勝利であります。

$ADComp | Select-Object -Property Enabled,Name,CanonicalName,OperatingSystem,
@{Name=”FinalLogon”;Expression={
(@([DateTime]::FromFileTime($_.LastLogon),[DateTime]::FromFileTime($_.LastLogonTimeStamp),[DateTime]$_.LastLogonDate) | Measure-Object -Maximum).Maximum
}} | Export-Csv -Path (“{0}_{1}_ADComputer.csv” -f (hostname),(Get-Date -Format “yyyyMMdd-hhmmss”)) -Encoding Default -NoTypeInformation



$ADUser | Select-Object -Property Enabled,Name,CanonicalName,samAccountName,
@{Name=”FinalLogon”;Expression={
(@([DateTime]::FromFileTime($_.LastLogon),[DateTime]::FromFileTime($_.LastLogonTimeStamp),[DateTime]$_.LastLogonDate) | Measure-Object -Maximum).Maximum
}} | Export-Csv -Path (“{0}_{1}_ADUser.csv” -f (hostname),(Get-Date -Format “yyyyMMdd-hhmmss”)) -Encoding Default -NoTypeInformation


最終ログオン日時、LastLogonDate が常に最新となっていればこんな苦労はないのに、、、

しかしまぁ、PowerShell があればなんてことはないので
何とかなります。

このメモが何時の日か誰かのお役に立ちますように。