Converting AD LastLogon to Time/Date

I am trying to get a list of AD users that have logged on in the last 30 days. The challenge for me here is converting the LastLogon to System.DateTime so that I can compare it with get-date. I read somewhere it can be done using “([DateTime]::FromFileTime($user.LastLogon))” however this is not working for me. At this point I feel like i am over complicating this and fundamentally missing something. Below is what I have so far. Any help would be greatly appreciated.

import-module ActiveDirectory
get-aduser -filter * -properties * | where {$.([DateTime]::FromFileTime($user.LastLogon)) -gt (get-date).AddDays(-30)} | Select-Object @{n=‘LastLogon’;e={[DateTime]::FromFileTime($.LastLogon)}}

Never mind. I figured it out.

get-aduser -filter * -properties LastLogon | Select-Object @{n=‘LastLogon’;e={[DateTime]::FromFileTime($.LastLogon)}} | where {$.‘LastLogon’ -gt (get-date).AddDays(-30)}

why not use the lastlogondate?

I did originally and the syntax was a lot less involved however in my results the dates are not the same. My account, for example, shows lastlogondate as 7/21/2016 and lastlogon shows 7/27/2016.

get-aduser mike -properties * | select Last

LastBadPasswordAttempt : 6/30/2016 9:28:42 AM
LastKnownParent :
lastLogoff : 0
lastLogon : 131141091505944509
LastLogonDate : 7/21/2016 8:12:40 PM
lastLogonTimestamp : 131136199607385225
PasswordLastSet : 6/5/2016 5:00:41 PM
pwdLastSet : 131096340413576251

get-aduser mike -properties * | Select-Object @{n=‘LastLogon’;e={[DateTime]::FromFileTime($_.LastLogon)}}

LastLogon

7/27/2016 12:05:50 PM

LastLogonDate is a converted version of LastLogonTimestamp and is replicated among DCs with up to a 14 day delay. Since you are querying 30 days back, LastLogonDate is appropriate if you understand the limitations. More on that later.

LastLogon is NOT replicated, but contains the user’s actual last login. To query against that you have to query every DC in your domain and select the most recent LastLogon, otherwise you won’t actually get their actual last logon.

Now say you query LastLogonDate/Timestamp and check for 30 days, since their could be an update delay of up to 14 days, it could read up to 14 days older than their actual last logon. That means that lastlogontimestamp could be 6/28, but they may have logged on say 7/5 and it not have updated lastlogontimestamp. So checking for 30 days against lastlogontimestamp means you are really checking for users who haven’t logged in from 15 to 30 days. If you wanted to check for over 30 days only, you can set it to 45 days and miss some users who haven’t logged in from 30 to 44 days.

In comes Search-ADAccount:

Search-ADAccount -AccountInactive -Timespan (New-TimeSpan -Days 30) -UsersOnly

Which is easier to use, in my opinion. Keeping in mind that Search-ADAccount looks at the lastlogonTimestamp that could be updated up to 14 days behind. But, Search-ADAccount adds 15 days to whatever you pass it to account for the delay. So if you wanted to check for accounts that certainly haven’t logged in in the last 30 days, you pass it 30 days. It then checks the lastlongontimestamp for dates older than 45 days.

Regardless, what you are doing isn’t going to give you the results you are after. To continue to use lastlogon, you must check every DC. To switch to lastlogontimestamp (or search-adaccount), you have to accept that users that have last logged in from 30 to 44 days may or may not be missed.

Thanks Craig. That is good advice. I changed my syntax to use LastLogonTimeStamp and increased the days to 45. I have already scripted some other things around this so I didn’t want to completely change it and start using Search-ADAccount but ill keep that command in mind in the future.