Getting LastLogon and LastLogonTimeStamp from ALL Domain Controllers into 1 output CSV

14.5k views Asked by At

So far I have this:

Get-ADDomainController -filter * | 
% {Get-ADUser -Filter "Enabled -eq 'True'" -server $_.name -Properties         Name,SamAccountName,Description,EmployeeID,EmployeeNumber,EmailAddress,LastLogon,Manager,Title,Department,Organization,Enabled -SearchBase "DC=webcoindustries,DC=com" | 
? {$_.EmployeeID -notlike "EXCLUDE" } | 
Select Name,SamAccountName,Description,EmployeeID,EmployeeNumber,EmailAddress,@{N='Last‌​Logon'; E={[DateTime]::FromFileTime($_.LastLogon)}},Manager,Title,Department,Organizatio‌​n,Enabled | 
Export-Csv "C:\scripts\AD_Export_Test\AD_Export_$($_.name).csv"}

This only pulls LastLogon into multiple CSV files (1 for each Domain Controller). However, what I would like to be done is for the script to also pull LastLogonTimeStamp, compare the two, and use the whichever one is most recent. I also would like to have the full end result only be in one final CSV file. Is this possible all in one script?

3

There are 3 answers

3
TheMadTechnician On BEST ANSWER

I think a simple Group, followed by Sort, and Select -First 1 in a ForEach loop would solve this problem.

Get-ADDomainController -filter * | 
% {Get-ADUser -Filter "Enabled -eq 'True' -and EmployeeID -notlike 'EXCLUDE'" -server $_.name -Properties         Name,SamAccountName,Description,EmployeeID,EmployeeNumber,EmailAddress,LastLogon,Manager,Title,Department,Organization,Enabled -SearchBase "DC=webcoindustries,DC=com" | 
Select Name,SamAccountName,Description,EmployeeID,EmployeeNumber,EmailAddress,@{N='Last‌​Logon'; E={[DateTime]::FromFileTime($_.LastLogon)}},Manager,Title,Department,Organizatio‌​n,Enabled}|
Group samaccountname |
ForEach{$_.Group | Sort LastLogon -Descending | Select -First 1} |
Export-Csv "C:\scripts\AD_Export_Test\AD_Export.csv" -NoTypeInformation

I also moved your EmployeeID -notlike "EXCLUDE" filter from the Where statement into your Get-ADUser filter, and got rid of the Where statement

2
Ansgar Wiechers On

To get a list of users with their most recent logon across all domain controllers store the usernames in a hashtable that you update whenever you find a user that isn't in the hashtable yet or has a more recent logon timestamp:

$users = @{}

Get-ADDomainController | % {
  Get-ADUser -Filter "Enabled -eq 'True'" -Server $_.Name -Property lastLogon | % {
    $user = $_.SamAccountName
    $time = [DateTime]::FromFileTime($_.lastLogon)

    if (-not $users.Contains($user) -or $users[$user] -lt $time) {
      $users[$user] = $time
    }
  }
}

Afterwards the hashtable can be exported to a CSV like this:

$users.GetEnumerator() | % {
  New-Object -Type PSCustomObject -Property [ordered]@{
    SamAccountName = $_.Name
    LastLogon      = $_.Value
  }
} | Export-Csv 'C:\path\to\lastlogons.csv' -NoType

or, if you really need that boatload of other attributes, like this:

$attributes = 'Name', 'SamAccountName', 'Description', 'EmployeeID',
              'EmployeeNumber', 'EmailAddress', 'Manager', 'Title',
              'Department', 'Organization', 'Enabled'

Get-ADUser -Filter "Enabled -eq 'True'" -Property $attributes |
  select $attributes, @{n='LastLogon';e={$users[$_.SamAccountName]}} |
  Export-Csv 'C:\path\to\lastlogons.csv' -NoType
4
Johan de Haan On

We use the following Function to determine the lastlogon

function Measure-LoggedOn {
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName=$true,Position=0)]
    $DistinguishedName,
    [string[]]$DomainControllers
)
$RealLastLogon = $null 
$LastusedDC = $null 
foreach ($DomainController in $DomainControllers) {
    try{
        $Obj = $null
        $Obj = Get-ADObject -Identity $DistinguishedName -Properties LastLogon -Server $DomainController
        Write-Verbose "[$($Obj.Name)] Last logon on $DomainController : $([DateTime]::FromFileTime($Obj.LastLogon))"
        if ($RealLastLogon -le [DateTime]::FromFileTime($Obj.LastLogon)) { 
            $RealLastLogon = [DateTime]::FromFileTime($Obj.LastLogon)
            $LastusedDC =  $DomainController
        }
    } catch {
        Write-Warning "Error checking LastLogon attribute for $DistinguishedName on Domain Controller $DomainController"
    }
}
return $RealLastLogon
}

This way, you could use the following code to export the properties to a CSV:

# Outside the loop, determine al DCs
$ADInfo = Get-ADDomain
[string[]]$DCs = $ADInfo.ReplicaDirectoryServers

Get-ADUser -Filter "Enabled -eq 'True'" -Properties Name,SamAccountName,Description,EmployeeID,EmployeeNumber,EmailAddress,Manager,Title,Department,Organization,Enabled -SearchBase "DC=webcoindustries,DC=com" | ` 
? {$_.EmployeeID -notlike "EXCLUDE" } | `
Select Name,SamAccountName,Description,EmployeeID,EmployeeNumber,EmailAddress,@{N='Last Logon'; E={(Measure-LoggedOn -DistinguishedName $_.DistinguishedName -DomainControllers $DCs)}},Manager,Title,Department,Organization,Enabled | `
Export-Csv "C:\scripts\AD_Export_Test\AD_Export.csv" -NoTypeInformation