最終ログイン時刻の取得
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