PowerShell Query: Find Active Directory Computers with Recent Logins (Last 30 Days)


58 views

When managing a Windows domain, administrators often need to identify inactive computers for cleanup or security audits. A common requirement is finding workstations (excluding servers) that have had user logins within a specific timeframe - in this case, the last 30 days.

Several factors make this more complex than a simple AD query:

  • Need to filter by computer objects only
  • Must distinguish workstations from servers
  • Requires accurate date comparison logic
  • Should handle large domains efficiently

Here's the improved PowerShell script that addresses all requirements:


# Get current date threshold
$dateThreshold = (Get-Date).AddDays(-30)

# Query AD with proper filtering
$computers = Get-ADComputer -Filter {
    OperatingSystem -notlike "*server*" -and 
    LastLogonDate -ge $dateThreshold
} -Properties OperatingSystem, LastLogonDate |
Select-Object Name, OperatingSystem, LastLogonDate

# Export results
$computers | Export-Csv -Path "C:\Temp\ActiveComputers.csv" -NoTypeInformation

For large domains, consider these enhancements:


# Add server OS exclusion list
$serverOSPatterns = @("*server*","*datacenter*","*enterprise*")

# Use LDAP filter for better performance
$ldapFilter = "(&(objectCategory=computer)(!(operatingSystem=*server*))(lastLogonTimestamp>={0}))" -f 
    [DateTime]::Now.AddDays(-30).ToFileTime()

Get-ADComputer -LDAPFilter $ldapFilter -Properties LastLogonDate |
Where-Object { $_.LastLogonDate -ge $dateThreshold }

If you need more granular control over the OS filtering:


# Define workstation OS patterns
$workstationOS = @("Windows 10*","Windows 11*")

Get-ADComputer -Filter * -Properties OperatingSystem, LastLogonDate |
Where-Object {
    $_.OperatingSystem -match ($workstationOS -join "|") -and
    $_.LastLogonDate -ge $dateThreshold
}

For global organizations, account for timezone differences in LastLogonDate:


$utcThreshold = (Get-Date).ToUniversalTime().AddDays(-30)
Get-ADComputer -Filter { LastLogonDate -ge $utcThreshold } -Properties LastLogonDate

As an admin managing a Windows domain, one of my recurring tasks is identifying which workstations are actually being used. Servers typically show consistent activity, but workstations might sit idle for months after employees depart. Here's how I solved this with PowerShell.

The key property we need is LastLogonDate, which represents the most recent authentication timestamp. Unlike LastLogon, this value gets replicated across domain controllers.

# Basic query to examine properties
Get-ADComputer -Filter * -Properties LastLogonDate,OperatingSystem | 
    Select-Object Name,OperatingSystem,LastLogonDate |
    Format-Table -AutoSize

To find machines logged into within 30 days, we'll use PowerShell's datetime comparison:

$cutoffDate = (Get-Date).AddDays(-30)
Get-ADComputer -Filter {OperatingSystem -like "*Workstation*" -and LastLogonDate -ge $cutoffDate} 
    -Properties LastLogonDate,OperatingSystem |
    Select-Object Name,OperatingSystem,LastLogonDate |
    Export-Csv -Path "C:\Temp\ActiveWorkstations.csv" -NoTypeInformation

For large domains, these improvements help:

  • Add -ResultPageSize 1000 for better performance
  • Use -SearchBase to limit to specific OUs
  • Include error handling for stale computers
try {
    $activeComputers = Get-ADComputer -Filter {
        OperatingSystem -like "*Workstation*" -and 
        Enabled -eq $true -and
        LastLogonDate -ge $cutoffDate
    } -Properties * -ErrorAction Stop
    
    $activeComputers | Export-Csv -Path "C:\reports\active_workstations.csv" -NoTypeInformation
}
catch {
    Write-Error "AD query failed: $_"
}

For environments where computer accounts rotate passwords regularly:

$active = Get-ADComputer -Filter {
    pwdLastSet -ge $cutoffDate.ToFileTime()
} -Properties pwdLastSet

Create a scheduled task to run weekly:

$action = New-ScheduledTaskAction -Execute "PowerShell.exe" 
    -Argument "-NoProfile -File C:\scripts\check_active_workstations.ps1"
$trigger = New-ScheduledTaskTrigger -Weekly -At 3am
Register-ScheduledTask -TaskName "AD Workstation Activity Report" 
    -Action $action -Trigger $trigger -RunLevel Highest