Sunday, March 7, 2010

Last Logon User and Time

Need to find out who the last person to log into a computer was and what time they did? Here you go!

CODE

$data = @()

$NetLogs = Get-WmiObject Win32_NetworkLoginProfile

foreach ($NetLog in $NetLogs) {
    if ($NetLog.LastLogon -match "(\d{14})") {
        $row = "" | Select Name,LogonTime
        $row.Name = $NetLog.Name
        $row.LogonTime=[datetime]::ParseExact($matches[0], "yyyyMMddHHmmss", $null)
        $data += $row
    }
}

$data | Sort LogonTime -Descending | Select -First
 code: copy : expand : collapse
EXPLANATION
The WMI class Win32_NetworkLoginProfile contains logon information for every valid session since the machine was booted. It does have limits, but this statement is generally true. We'll grab all instances of this and parse through one at a time.

Not all logons have a valid time stamp. Only interactive logons via the console or RDP do. So, we must filter them out. That's where we use if ($NetLog.LastLogon -match "(\d{14})"). This looks for a match of 14 decimals. (\d = decimals, {14} = 14 characters). Because the timestamp is not in a standard format we cannot use PowerShell's Get-Date, we must utilize .Net's [datetime] to parse it. DateTime's ParseExact is in the format (InputString,Format,IFormatProvider). Here we have $matches[0] as the input string (created by PoSh when using the -matches comparison). Please see http://msdn.microsoft.com/en-us/library/system.globalization.datetimeformatinfo.aspx for the DateTimeFormat information. Since we're not using any other custom Format interface the 3rd input is $null)

Once all the data is gathered and filtered out we only want to show the most recent logon time. To do this we sort by LogonTime in a Descending order and only Select the -First.

Done!

1 comments:

Anonymous said...

I just can't help myself. I've been working on this a bit more and have streamlined the process. It now runs faster and is a bit cleaner.

Get-WmiObject Win32_NetworkLoginProfile |`
Sort -Descending LastLogon |`
Select * -First 1 |`
? {$_.LastLogon -match "(\d{14})"} |`
% {$row = "" | Select Name,LastLogon ;`
$row.Name=$_.Name ;`
$row.LastLogon=[datetime]::ParseExact($matches[0], "yyyyMMddHHmmss", $null) ;`
$row}