# AllLastLogonAndCount.ps1 # For each user account found on each domain controller in the domain this # PowerShell script retrieves the values of logonCount, and lastLogon. The # script retains the latest lastLogon value and the total logonCount for each # user over all DCs. # # Copyright (c) 2018 Richard L. Mueller # Version 2.1 - December 20, 2018 # # ---------------------------------------------------------------------- # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. # Retrieve information for the current domain. $D = [system.directoryservices.activedirectory.Domain]::GetCurrentDomain() $Domain = [ADSI]"LDAP://$D" # Setup the DirectorySearcher object. $Searcher = New-Object System.DirectoryServices.DirectorySearcher $Searcher.PageSize = 200 $Searcher.SearchScope = "subtree" # Filter on all enabled users. $Searcher.Filter = "(&(objectCategory=person)(objectClass=user)(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" # To find all users, whether enabled or not, use this filter. # $Searcher.Filter = "(&(objectCategory=person)(objectClass=user))" # Specify attribute values to retrieve. $Searcher.PropertiesToLoad.Add("distinguishedName") > $Null $Searcher.PropertiesToLoad.Add("sAMAccountName") > $Null $Searcher.PropertiesToLoad.Add("logonCount") > $Null $Searcher.PropertiesToLoad.Add("lastLogon") > $Null # Hash table of users and lastLogon. # Key is user DN, value is latest lastLogon. $UserLast = @{} # Hash table of users and logonCount. # Key is user DN, value is cumulative total logonCount. $UserCount = @{} # Query every domain controller in the domain. ForEach ($DC In $D.DomainControllers) { # Ping each domain controller. If (ping $DC -n 1 -w 1000 | find "Reply from") { # DC responded. # Trap any error, but do not halt the script. The error message # will not be redirected, but will display at the prompt. Trap {Write-Host "DC $Server - $_" ` -foregroundcolor red -backgroundcolor black; Continue;} $Server = $DC.Name $Results = $Null # Specify the DC and the domain in the Base of the query. $Base = "LDAP://$Server/" + $Domain.distinguishedName $Searcher.SearchRoot = $Base $Results = $Searcher.FindAll() If($Results) { # Enumerate all users found on this DC. ForEach ($Result In $Results) { # Retrieve the values for this user on this DC. $DN = $Result.Properties.Item("distinguishedName") $NTName = $Result.Properties.Item("sAMAccountName") $Key = "$DN ($NTName)" $LogonCount = $Result.Properties.Item("logonCount")[0] If (-Not $LogonCount) {$LogonCount = 0} $LL = $Result.Properties.Item("lastLogon")[0] If (-Not $LL) {$LL = 0} $Last = ([DateTime]$LL).AddYears(1600).ToLocalTime() # Check if user has been seen. If ($UserLast.ContainsKey($Key)) { # Retain the latest lastLogon value. If ($Last -gt $UserLast[$Key]) {$UserLast[$Key] = $Last} } Else { # Add this user to the hash table. $UserLast.Add($Key, $Last) } # Check if user has been seen, and logonCount greater than 0. If ($UserCount.ContainsKey($Key) -And ($LogonCount -gt 0)) { # Add logonCount to the total. $UserCount[$Key] = $UserCount[$Key] + $LogonCount } Else { # Add this user to the hash table. $UserCount.Add($Key, $LogonCount) } } } } Else { Write-Host "DC $DC is not available -foregroundcolor red -backgroundcolor black" } } # Output a header line, comma delimited. "DN (NTName),Last Logon,Total Logon Count" # Enumerate all users found. ForEach ($DN In $UserLast.Keys) { $LastLogon = $UserLast[$DN] If ($LastLogon -lt ([DateTime]0).AddYears(1602).ToLocalTime()) { $LastLogon = "Never" } If ($UserCount.ContainsKey($DN)) {$Total = $UserCount[$DN]} Else {$Total = 0} # Output comma delimited. Distinguished names are quoted because they have # embedded commas. """$DN"",$LastLogon,$Total" }