Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function Get-RealLogonDate {
- [CmdletBinding()]
- Param (
- [Parameter(Mandatory = $true,
- Position = 0)]
- [String]$sAMAccountName,
- [Parameter(Mandatory = $true,
- Position = 1)]
- [String]$Domain
- )
- # Build a domain object so we can get a list of domain controllers
- try {
- $domainContext = New-Object System.DirectoryServices.ActiveDirectory.DirectoryContext('Domain', $Domain)
- $domainInfo = [DirectoryServices.ActiveDirectory.Domain]::GetDomain($domainContext)
- }
- catch {
- throw ('Unable to connect to {0}: {1}' -f $Domain, $_.exception.message)
- }
- # Pull out all of the dc's in the domain.
- [array]$dcList = $domainInfo.DomainControllers | foreach { $_.name }
- Write-Verbose -Message ('[GetRealLogonDate] Found {0} DCs in {1}' -f $dcList.count, $Domain)
- # Define a script block which we'll use to feed into a job.
- $queryBlock = {
- Param (
- [Parameter(Mandatory = $true,
- Position = 0)]
- [String]$sAMAccountName,
- [Parameter(Mandatory = $true,
- Position = 1)]
- [String]$ComputerName
- )
- # Search the domain controller for the user in question
- $searcher = new-object System.DirectoryServices.DirectorySearcher([ADSI]"LDAP://$ComputerName")
- $searcher.filter = "(&(objectClass=User)(lastlogon=*)(sAMAccountName=$sAMAccountName))"
- [void]$searcher.PropertiesToLoad.Add('lastlogon')
- try {
- $userObj = $searcher.FindOne()
- }
- catch {
- return $null
- }
- # 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)
- Write-Output $(New-Object -TypeName PSObject -Property @{ DC = $ComputerName; sAMAccountName = $sAMAccountName; LastLogon = [int64]$($userObj.Properties.lastlogon | Out-String).trim() })
- }
- # Go through each DC in the list and query for the user account.
- $queryQueue = New-Object System.Collections.ArrayList
- for ($i = 0; $i -lt $dcList.count; $i++) {
- Write-Verbose ('[GetRealLogonDate] Running jobs: {0}' -f (Get-Job -State Running).Count)
- # If there are more than 10 jobs running wait until they finish.
- While ((Get-Job -State Running).Count -ge 10) {
- Start-Sleep -Seconds 3
- }
- Write-Verbose ('[GetRealLogonDate] Starting job for {0}' -f $dcList[$i])
- Start-Job -Name $dcList[$i] -ScriptBlock $queryBlock -ArgumentList $sAMAccountName, $dcList[$i] | Out-Null
- # Get any completed jobs and add them to our query queue.
- Get-Job -State Completed | Where { $_.Name -like "*.$Domain.*" } | Receive-Job -Wait -AutoRemoveJob | foreach { [void]$queryQueue.Add($_) }
- }
- # Look for and get any pending jobs and then receive them as well.
- Write-Verbose ('[GetRealLogonDate] Waiting for running jobs to finish')
- Get-Job | Wait-Job | Receive-Job -Wait -AutoRemoveJob | foreach { [void]$queryQueue.Add($_) }
- # Init log to 0 and then go through each result we got and compare to the value of log (starting with 0).
- # Since the value for lastlogon is an integer we can easily compare to see which number is greater. The goal
- # is to get the number which is highest and then convert that to a datetime object.
- $log = 0
- for ($q = 0; $q -lt $queryQueue.count; $q++) {
- if ($queryQueue[$q].LastLogon -like $null) { continue }
- if ($queryQueue[$q].LastLogon -gt $log) { $log = $queryQueue[$q].LastLogon }
- }
- # Return the value in $log and convert to a datetime object.
- Write-Output $([datetime]::FromFileTime($log))
- }
Advertisement
Add Comment
Please, Sign In to add comment