Search Active Directory for computers logged in, in the last 30 days

I am trying to do a PowerShell search of AD to find computers only (not servers or others) that have been logged into within the last 30 days. I have most of the script written except for the limiting of 30 days part. Any help would be greatly appreciated.

Get-ADComputer -Filter * -Properties * | FT Name, OperatingSystem, LastLogonDate -Autosize | Out-File C:\Temp\ComputerLastLogonDate.csv


Get-ADComputer -Filter * -Properties *

Only get the properties that you intend to use... it's more efficient. Retrieving all the properties of all computers in the domain when you don't really need all the properties is unnecessarily demanding on your domain controller. It's wasteful.

Get-ADComputer -Filter * -Properties OperatingSystem, LastLogonDate is better, since you don't need all the properties. (The 'Name' property is always included.)

| FT Name, OperatingSystem, LastLogonDate -Autosize

Don't format output until the very end. In other words, Format-Table and Format-List should be the very final cmdlets in the entire chain of cmdlets that data is piped to.

Get-ADComputer -Filter * -Properties OperatingSystem, LastLogonDate | Where { $_.LastLogonDate -GT (Get-Date).AddDays(-30) }

This is a little better, but there's still some inefficiency, since you are still retrieving a data set of all computers... you could let the domain controller do the filtering for you.

$LastMonth = $(((Get-Date).AddDays(-30)).ToFileTime())

Get-ADComputer -LDAPFilter "(lastLogonTimeStamp>=$LastMonth)" -Properties OperatingSystem,LastLogonDate

The reason why I used the lastLogonTimeStamp there (which is a "file time," not a .NET DateTime,) is because "LastLogonDate" is not a real LDAP attribute. LastLogonDate is simply PowerShell's helpful way of automatically converting the lastLogonTimestamp attribute for you. lastLogonTimestamp is the "real" LDAP attribute.

Allowing the domain controller to return a filtered set to you, instead of the full set of ALL computers, means there is less data going over the wire and less data for PowerShell to process.

Also note that you are going to have to deal with computers that:

  • Have a (null) LastLogonDate
  • Have a LastLogonDate of 1/1/1601, or the beginning of the epoch.

Your command doesn't filter for only workstations at all.

You need to use the LastLogonTimeStamp field so that you can easily filter on it then convert it to a DateTime for export.

This information is also readily available online. Like this example here, that I slightly modified to return only workstations. Notice they query only the properties needed. It is more efficient. Also, I have no idea why they have a $domain variable in this script. It appears completely useless.

# Gets time stamps for all computers in the domain that have NOT logged in since after specified date 
# Mod by Tilo 2013-08-27 
import-module activedirectory  
$domain = "domain.mydom.com"  
$DaysInactive = 90  
$time = (Get-Date).Adddays(-($DaysInactive)) 

# Get all AD computers with lastLogonTimestamp less than our time 
Get-ADComputer -Filter {LastLogonTimeStamp -lt $time -and OperatingSystem -notlike "*server*"} -Properties LastLogonTimeStamp,OperatingSystem | 

# Output hostname and lastLogonTimestamp into CSV 
select-object Name,@{Name="Stamp"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}} | export-csv OLD_Computer.csv -notypeinformation

Referenced from here: https://gallery.technet.microsoft.com/scriptcenter/Get-Inactive-Computer-in-54feafde

Also see the following references in regard to this:

The LastLogonTimeStamp attribute / what it was designed for

Converting TimeStamp to DateTime