evetsleep

Get-RealLogonDate

Mar 3rd, 2015
791
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function Get-RealLogonDate {
  2.     [CmdletBinding()]
  3.     Param (
  4.         [Parameter(Mandatory = $true,
  5.                    Position = 0)]
  6.         [String]$sAMAccountName,
  7.        
  8.         [Parameter(Mandatory = $true,
  9.                    Position = 1)]
  10.         [String]$Domain
  11.     )
  12.  
  13.     # Build a domain object so we can get a list of domain controllers
  14.     try {
  15.         $domainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
  16.         $domainInfo = [DirectoryServices.ActiveDirectory.Domain]::GetDomain($domainContext)
  17.     }
  18.     catch {
  19.         throw ('Unable to connect to {0}: {1}' -f $Domain, $_.exception.message)
  20.     }
  21.    
  22.     # Pull out all of the dc's in the domain.
  23.     [array]$dcList = $domainInfo.DomainControllers | foreach { $_.name }
  24.     Write-Verbose -Message ('[GetRealLogonDate] Found {0} DCs in {1}' -f $dcList.count, $Domain)
  25.    
  26.     # Define a script block which we'll use to feed into a job.
  27.     $queryBlock = {
  28.         Param (
  29.             [Parameter(Mandatory = $true,
  30.                        Position = 0)]
  31.             [String]$sAMAccountName,
  32.            
  33.             [Parameter(Mandatory = $true,
  34.                        Position = 1)]
  35.             [String]$ComputerName
  36.         )
  37.        
  38.         # Search the domain controller for the user in question
  39.         $searcher = new-object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$ComputerName")
  40.         $searcher.filter = "(&(objectClass=User)(lastlogon=*)(sAMAccountName=$sAMAccountName))"
  41.         [void]$searcher.PropertiesToLoad.Add('lastlogon')
  42.         try {
  43.             $userObj = $searcher.FindOne()
  44.         }
  45.         catch {
  46.             return $null
  47.         }
  48.        
  49.         # Write out a match to include the DC, their name, and the last long as a number (this is important, we don't want to convert it yet)
  50.         Write-Output $(New-Object -TypeName PSObject -Property @{ DC = $ComputerName; sAMAccountName = $sAMAccountName; LastLogon = [int64]$($userObj.Properties.lastlogon | Out-String).trim() })
  51.     }
  52.    
  53.     # Go through each DC in the list and query for the user account.
  54.     $queryQueue = New-Object System.Collections.ArrayList
  55.     for ($i = 0; $i -lt $dcList.count; $i++) {
  56.         Write-Verbose ('[GetRealLogonDate] Running jobs: {0}' -f (Get-Job -State Running).Count)
  57.         # If there are more than 10 jobs running wait until they finish.
  58.         While ((Get-Job -State Running).Count -ge 10) {
  59.             Start-Sleep -Seconds 3
  60.         }
  61.        
  62.         Write-Verbose ('[GetRealLogonDate] Starting job for {0}' -f $dcList[$i])
  63.         Start-Job -Name $dcList[$i] -ScriptBlock $queryBlock -ArgumentList $sAMAccountName, $dcList[$i] | Out-Null
  64.        
  65.         # Get any completed jobs and add them to our query queue.
  66.         Get-Job -State Completed | Where { $_.Name -like "*.$Domain.*" } | Receive-Job -Wait -AutoRemoveJob | foreach { [void]$queryQueue.Add($_) }
  67.     }
  68.    
  69.     # Look for and get any pending jobs and then receive them as well.
  70.     Write-Verbose ('[GetRealLogonDate] Waiting for running jobs to finish')
  71.     Get-Job | Wait-Job | Receive-Job -Wait -AutoRemoveJob | foreach { [void]$queryQueue.Add($_) }
  72.    
  73.     # Init log to 0 and then go through each result we got and compare to the value of log (starting with 0).
  74.     # Since the value for lastlogon is an integer we can easily compare to see which number is greater.  The goal
  75.     # is to get the number which is highest and then convert that to a datetime object.
  76.     $log = 0
  77.     for ($q = 0; $q -lt $queryQueue.count; $q++) {
  78.         if ($queryQueue[$q].LastLogon -like $null) { continue }
  79.         if ($queryQueue[$q].LastLogon -gt $log) { $log = $queryQueue[$q].LastLogon }
  80.     }
  81.    
  82.     # Return the value in $log and convert to a datetime object.
  83.     Write-Output $([datetime]::FromFileTime($log))
  84. }
Advertisement
Add Comment
Please, Sign In to add comment