PowerShell - Filter a list Computers by LastLogon Date

2012, Jan 29    

I needed a script to filter a list of computers by the number of days since the computer was last logged onto.  This is my solution to that.  When supplied a list of computers, this will return the ones that have been Active (Logged On) within the Last X amount of days.  Where X is supplied as $DaysSinceLastLogon.  I’ve populated the PowerShell Comment Doc, so check out the Examples supplied in there for usage.

<#
.SYNOPSIS
Filter a list Computers by LastLogon Date.
.DESCRIPTION
When supplied a list of computers, this will return the ones that have been Active (Logged On) within the Last X amount of days.  Where X is supplied as $DaysSinceLastLogon.
.PARAMETER ComputerNames
Object supplied via piped in result from a Get-ADComputer query, or similar.  Alias: Name
.PARAMETER DaysSinceLastLogon
Default: 180.  Number of days since Last Logon.  Used to justify an Active Computer.
.INPUTS
System.Object	ComputerNames
System.Int32	DaysSinceLastLogon
.OUTPUTS
List of Computer Names.
.EXAMPLE
Get-ADComputer Computer0123A | Get-CompByUser
Active Computers:  1
Total Computers:   1
The Active Computers are:

Hostname      LastLogon            OperatingSystem
--------      ---------            ---------------
Computer0123A 1/26/2012 8:55:20 PM Windows 7 Enterprise
.NOTES
.LINK
go.vertigion.com/PowerShell-Get-CompByActivity
function Get-CompByActivity {
	param(
		[Alias("Name")]
		[parameter(
			Position = 0,
			Mandatory = $true,
			ValueFromPipeline = $true,
			ValueFromPipelineByPropertyName = $true,
			HelpMessage = "Enter the Name of a computer account."
		)]
		$ComputerNames
		,
		[parameter(Mandatory = $false)]
		[int] $DaysSinceLastLogon = 180
	)

	Begin {
		$OutputList = @()
		$Domain = $(Get-ADDomain).DNSRoot
		$DCs = Get-ADDomainController
		$TotalComputers = 0
		
		function Measure-Latest {
			BEGIN { $latest = $null }
			PROCESS {if (($_ -ne $null) -and (($latest -eq $null) -or ($_ -gt $latest))) {$latest = $_}}
			END { $latest }
		}
	}
	
	Process {
		Write-Debug "ComputerNames: $ComputerNames"
		$TotalComputers += ($ComputerNames | Measure-Object).Count
		
		Write-Debug "ComputerNames Type:  $(($ComputerNames.GetType()).Name)"
		switch -regex ($(($ComputerNames.GetType()).Name)) {
			"PSCustomObject|ADComputer" {
				foreach ($Computer in $ComputerNames) {
					Write-Debug "Computer: $Computer"
					$LastLogon = [datetime]::FromFileTime($($(foreach ($DC in $DCs) {
						(Get-ADComputer $Computer.Name -Server $DC.Name -Properties LastLogon).LastLogon
					}) | Measure-Latest))
					if (($(Get-Date)-$LastLogon).Days -lt $DaysSinceLastLogon) {
						$NewObject = New-Object PSObject
						Add-Member -InputObject $NewObject NoteProperty 'Hostname' $Computer.Name.ToUpper()
						Add-Member -InputObject $NewObject NoteProperty 'LastLogon' $LastLogon
						Add-Member -InputObject $NewObject NoteProperty 'OperatingSystem' (Get-ADComputer ($Computer.Name) -Properties OperatingSystem).OperatingSystem
						$OutputList += $NewObject
					}
				}
			}
			default { Throw("Unable to handle that Type: $(($ComputerNames.GetType()).Name)") }
		}
	}
	
	End {
		Write-Debug "ComputerNames Type:  $(($ComputerNames.GetType()).Name)"
		Write-Output "Active Computers:  $($OutputList.Count)`nTotal Computers:   $TotalComputers`nThe Active Computers are:"
		Write-Output $OutputList | sort @{expression="LastLogon";Ascending=$true},@{expression="Hostname";Ascending=$true} | ft -auto
	}
}

Hope it helps others out there.  Just add the function to your PowerShell Profile or as a Functions in a script to make it available!