Finding Active Windows 7 Machines In Active Directory

Quick one today (won’t even need a TL;DR), with Windows 7 no longer supported (ESU program being the exception) we’re all making sure either existing or new clients have no leftover machines on the domain.

Here is a quick PowerShell snippet to find any Win 7 machines that have logged onto the domain in the last 30 days (change the number as you see fit, but mind the caveat below).

$ActiveAfter = (Get-Date).AddDays(-30)
Get-ADComputer -Filter {(OperatingSystem -like "Windows 7*") -and (LastLogonDate -gt $ActiveAfter)} -Properties OperatingSystem, LastLogonDate

And some sample output:

DistinguishedName : CN=PC-041,OU=Computers,OU=Company,DC=AD,DC=local
DNSHostName       : PC-041.AD.local
Enabled           : True
LastLogonDate     : 14/01/2020 5:25:36 PM
Name              : PC-041
ObjectClass       : computer
ObjectGUID        : 2f54569e-59c5-40ee-ab5c-34807364827c
OperatingSystem   : Windows 7 Professional
SamAccountName    : PC-041$
SID               : S-1-5-21-1520911859-599951107-2041482618-2313

LastLogonDate vs lastLogonTimestamp vs lastLogon

We’re using the LastLogonDate property to obtain a timestamp of when the machine last logged onto the domain. LastLogonDate doesn’t actually exist in AD, it’s a cooked value of the lastLogonTimestamp AD property that PowerShell helpfully converts from the FileTime format, to a friendlier DateTime format.

Now, lastLogonTimestamp is a value that is replicated between all domain controllers. If PC1 authenticates against DC2, DC1 and DC3 will both know about it and update their local lastLogonTimestamp values. This means we can run our script against any domain controller and get an accurate list of recently authenticated machines companywide. But life is rarely that simple, and this is no exception.

The one caveat with lastLogonTimestamp is that in order to reduce replication traffic, this value is only updated every 14 days (by default). There are some extra technicalities around this number, but for our purposes 14 days is accurate enough. What this means for our example above, if PC1 had its lastLogonTimestamp value updated 7 days ago, and authenticates again, the value from 7 days ago will remain.

In short, if you use the above script, you should set your $ActiveAfter value to one that is greater than 14 (or rather less than -14 since we’re counting backwards).

There is a another value, lastLogon, which is not replicated, but is updated on each logon. There is not cooked value that PowerShell provides for this, so you will need to do the conversion yourself, but it will be more accurate as long as you only have a single domain controller or you query all domain controllers and extract the most recent value.