最終ログイン時刻の取得

ActiveDirectory環境で、最終ログイン時刻を取得しようとすると、ドメインが「2003ネイティブ」の場合は「lastLogonTimestamp」を取得すればいいらしい*1んですが、残念ながら自分のところは未だに2000ネイティブのままだったりします。
このためだけに2003ネイティブへ移行するのは、ちょっと怖いなーなんて思ってしまうので、以下のようにしました。

2020/01/06 追記
ドメインの機能レベルが2008までしか検証できてないですが、lastLogonTimestamp と lastLogonでは更新されるタイミングが異なるようで、最新の最終ログイン日時を取得したい場合は、やはり各ドメインコントローラから lastLogon を取得した方がいいようです。
2020/01/06 追記ここまで


さくっと一覧になってくれると嬉しいので、エクセルVBAで。

Private Sub Workbook_Open()
    Dim objCon As ADODB.Connection
    Dim objCom As ADODB.Command
    Dim rs As ADODB.Recordset
    Dim objUser As IADsUser
    Dim objLastLogon As Object
    Dim varLastLogon As Variant
    Dim lngRow As Long
    Dim aryRow() As Variant
    Dim Svrs() As String
    Dim i As Long
    Dim strDC As String
    
    Const strDomain = "ad.example.com"
    strDC = "DC=" & Replace(strDomain, ".", ",DC=")
    
    If MsgBox(strDomain & "内の全ユーザについて、最終ログイン時刻を取得します。結構時間かかりますが、実行しますか?", vbYesNo + vbQuestion) = vbNo Then Exit Sub
    
    
    Sheet1.UsedRange.Clear
    
    Sheet1.Cells(1, 1).Value = "id"
    Sheet1.Cells(1, 2).Value = "有効/無効"
    Sheet1.Cells(1, 3).Value = "氏名"
    Sheet1.Cells(1, 4).Value = "所属"
    Sheet1.Cells(1, 5).Value = "最終ログイン"
    
    Set objCon = New ADODB.Connection
    Set objCom = New ADODB.Command
    
    objCon.Open "Provider=ADsDSOObject;"
    
    ' DCの一覧を取得
    With objCom
        .ActiveConnection = objCon
        .Properties("Page Size") = 20000
        .CommandText = "<LDAP://" & strDomain & "/OU=Domain Controllers," & strDC & ">;(objectClass=computer);name;subtree"
    End With
    Set rs = objCom.Execute

    i = 0
    Do Until rs.EOF
        ReDim Preserve Svrs(i)
        Svrs(i) = rs("name")
        
        Sheet1.Cells(1, i + 6).Value = Svrs(i)
        
        i = i + 1
        rs.MoveNext
    Loop
    rs.Close
    
    ' Userの一覧を取得
    With objCom
        .ActiveConnection = objCon
        .Properties("Page Size") = 20000
        .CommandText = "<LDAP://" & strDomain & ">;(&(objectCategory=person)(objectClass=user));cn,displayname,description;subtree"
    End With
    On Error Resume Next
    
    Set rs = objCom.Execute
    
    lngRow = 2
    Do Until rs.EOF
        ReDim aryRow(1 To UBound(Svrs) + 6)
        
        aryRow(1) = rs("cn")
        aryRow(3) = rs("displayname")
        
        ' Userごとに全DCへ最終ログイン時刻を確認
        For i = 0 To UBound(Svrs)
            Application.StatusBar = String(UBound(Svrs) - i, "・")
            
            Set objUser = GetObject("LDAP://" & Svrs(i) & "/cn=" & rs("cn") & ",CN=Users," & strDC)
            
            If i = 0 Then
                If objUser.AccountDisabled Then
                    aryRow(2) = "無効"
                Else
                    aryRow(2) = ""
                End If
                
                aryRow(4) = objUser.Department
            End If
            
            Set objLastLogon = objUser.Get("lastLogon")
            
            ' 1601年1月1日からの経過時間(単位はマイクロ秒?)を通常の日付に
            ' 時差は考慮されてないので、正確さを求めるならもう一工夫必要
            varLastLogon = 0
            varLastLogon = objLastLogon.HighPart * (2 ^ 32) + objLastLogon.LowPart
            varLastLogon = varLastLogon / (60 * 10000000)
            varLastLogon = varLastLogon / 1440
            varLastLogon = varLastLogon + #1/1/1601#
            
            aryRow(i + 6) = varLastLogon
            DoEvents
        Next i
        Application.StatusBar = ""
        
        With Sheet1
            aryRow(5) = "=Max(" & .Cells(lngRow, 6).Address & ":" & .Cells(lngRow, UBound(Svrs) + 6).Address & ")"
            .Range(.Cells(lngRow, 1), .Cells(lngRow, UBound(Svrs) + 6)).Formula = aryRow
            .Range(.Cells(lngRow, 5), .Cells(lngRow, UBound(Svrs) + 6)).NumberFormatLocal = "yyyy/m/d h:mm"
        End With
        
        DoEvents
        lngRow = lngRow + 1
        
        If Err.Number <> 0 Then Err.Clear
        rs.MoveNext
        
    Loop
    
    rs.Close
    objCon.Close
    
    Set rs = Nothing
    Set objCom = Nothing
    Set objCon = Nothing
    
    Call MsgBox("終了しました。", vbOKOnly + vbInformation)
End Sub