Another short article with little context today.
The PowerShell script below will produce a report showing the Last Logon time of all enabled Active Directory users, it will also connect to Exchange On-Premise and request the last logon date of the mailbox. This can be useful to identify user accounts which are no longer in active use, even in organisations where mailboxes may have been retained once a user left.
There’s also a nifty status update built in that will tell you exactly how far the script has progressed and show an estimated time to completion.
The Script
# Locate all users that have not logged in within 12 months
$InactiveMonths = 12
$ExchangePowerShellEndpoint = "https://*Server*/PowerShell/"
$ExchangeAuthenticationModel = "Kerberos"
$UserCredential = Get-Credential -Message "Enter your credentials used to log into the Exchange Admin Portal"
$Months = (Get-Date).Addmonths(-($InactiveMonths))
$Users = Get-ADUser -Filter {LastLogonTimeStamp -lt $Months -and enabled -eq $true} -Properties LastLogonTimeStamp, mail |
select-object Name,@{Name="LastLogon"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp).ToString('dd-MM-yyyy')}},SamAccountName,UserPrincipalName, mail
Write-Host "Located $($Users.count) users"
# Connect to Exchange
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ExchangePowerShellEndpoint -Authentication $ExchangeAuthenticationModel -Credential $UserCredential
Import-PSSession $Session -DisableNameChecking -AllowClobber
# For each user, get the last mailbox login time
$currentIndex = 1
$startTime = Get-Date
foreach ($user in $users) {
# Estimate time to completion
$estimation = " "
$now = Get-Date
if ($currentIndex -gt 0) {
$elapsed = $now - $startTime # how much time has been spent
$average = $elapsed.TotalSeconds / $currentIndex # how many seconds per site
$totalSecondsToGo = ($users.Count - $currentIndex) * $average # seconds left
$span = New-TimeSpan -Seconds $totalSecondsToGo # time left
$estimatedCompletion = $now + $span # when it will be complete
$estimation = $estimatedCompletion.ToString() # readable estimation
}
# Show progress and estimated completion
Write-Progress -Id 0 -Activity "Retrieving Exchange Mailbox Stats" -Status "$currentIndex of $($Users.Count), Est Completion - $($estimation)" -PercentComplete (($currentIndex / $Users.Count) * 100)
# Get the mailboxes last logon time
try {
$mailboxStats = Get-MailboxStatistics -Identity $user.mail -ErrorAction Stop
$lastLogon = $mailboxStats.LastLogonTime
if($lastLogon -ne $null) {
$lastLogon = (Get-Date $lastLogon).ToShortDateString()
$user | Add-Member -Name 'mailboxLastAccess' -Type NoteProperty -Value $lastLogon
}
} catch {
$user | Add-Member -Name 'mailboxLastAccess' -Type NoteProperty -Value $null
}
$currentIndex++
}
Write-Progress -Id 0 -Activity " " -Status " " -Completed
# Export to CSV
$Users | export-csv C:\temp\LastLogOn_Users.csv -notypeinformation -noclobber
Hello, thank you very much for your script it save my life. But I have a little problem.
if a select 26 months for example I have 250 results and in the csv file I have all informations.
But if I select 24 months I have 900 results and in the csv file I dont have last exchange login column exported.
Like if too many results is not supported by the export function.
Have u got a idea about this?
PS: sorry english is not my native language
LikeLike