I recall back in the days of Windows Server 2000 where it was the norm to see the last user that logged into a machine. Whilst that option is still available using group policy, I wanted to get a timestamp of a machine’s login history using Powershell in order to get more information on what’s happening. Furthermore, I wanted to share get computer last login information using Powershell.
I should explicitly note that this script is not the same as the Get Last Logon Date For All Users in Your Domain. That script checks Active Directory for last login information, while this script specifically checks a local or remote computer’s last login info. With that said, the machine you want to query must be online since we’re going to be checking the event logs to get this data.
Script Prerequisites
This script uses the machine’s Event Security log so you will need run with Administrator rights. This is built-in to the function using the #requires -RunasAdministrator.
Powershell Parameters
I thought it would be helpful to get as much useful data so I added several useful parameters. Let’s go over them now.
-ComputerName
Description: By default this will use the local computer, but you can specify other computers in a comma separated format or through an array variable.
-SamAccountName
Description: This will only output the SamAccountName that you specified. All other users would be excluded and cannot be used with ExcludeSamAccountName
-ExcludeSamAccountName
Description: This will exclude the SamAccountName that you specified. All other users would be displayed and cannot be used with SamAccountName
-LoginEvent
Description: This will filter which event types you would like to display. Only one option can be selected and the only valid options are ‘SuccessfulLogin’, ‘FailedLogin’, ‘Logoff’, ‘DisconnectFromRDP’. If a value is not specified, it will default to ‘SuccessfulLogin’
-DaysFromToday
Description: This will query how many days back you would like to search for. The default is 3 days.
-MaxEvents
Description: This will set the maximum number of events to display.
-Credential
Description: Allow other credentials to be used for remote machines.
Get Computer Last Login Information Using Powershell
Function Get-LastLoginInfo { #requires -RunAsAdministrator <# .Synopsis This will get a Information on the last users who logged into a machine. More info can be found: https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/basic-audit-logon-events .NOTES Name: Get-LastLoginInfo Author: theSysadminChannel Version: 1.0 DateCreated: 2020-Nov-27 .EXAMPLE Get-LastLoginInfo -ComputerName Server01, Server02, PC03 -SamAccountName username .LINK https://thesysadminchannel.com/get-computer-last-login-information-using-powershell - #> [CmdletBinding(DefaultParameterSetName="Default")] param( [Parameter( Mandatory = $false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, Position = 0 )] [string[]] $ComputerName = $env:COMPUTERNAME, [Parameter( Position = 1, Mandatory = $false, ParameterSetName = "Include" )] [string] $SamAccountName, [Parameter( Position = 1, Mandatory = $false, ParameterSetName = "Exclude" )] [string] $ExcludeSamAccountName, [Parameter( Mandatory = $false )] [ValidateSet("SuccessfulLogin", "FailedLogin", "Logoff", "DisconnectFromRDP")] [string] $LoginEvent = "SuccessfulLogin", [Parameter( Mandatory = $false )] [int] $DaysFromToday = 3, [Parameter( Mandatory = $false )] [int] $MaxEvents = 1024, [System.Management.Automation.PSCredential] $Credential ) BEGIN { $StartDate = (Get-Date).AddDays(-$DaysFromToday) Switch ($LoginEvent) { SuccessfulLogin {$EventID = 4624} FailedLogin {$EventID = 4625} Logoff {$EventID = 4647} DisconnectFromRDP {$EventID = 4779} } } PROCESS { foreach ($Computer in $ComputerName) { try { $Computer = $Computer.ToUpper() $Time = "{0:F0}" -f (New-TimeSpan -Start $StartDate -End (Get-Date) | Select -ExpandProperty TotalMilliseconds) -as [int64] if ($PSBoundParameters.ContainsKey("SamAccountName")) { $EventData = " *[EventData[ Data[@Name='TargetUserName'] != 'SYSTEM' and Data[@Name='TargetUserName'] != '$($Computer)$' and Data[@Name='TargetUserName'] = '$($SamAccountName)' ] ] " } if ($PSBoundParameters.ContainsKey("ExcludeSamAccountName")) { $EventData = " *[EventData[ Data[@Name='TargetUserName'] != 'SYSTEM' and Data[@Name='TargetUserName'] != '$($Computer)$' and Data[@Name='TargetUserName'] != '$($ExcludeSamAccountName)' ] ] " } if ((-not $PSBoundParameters.ContainsKey("SamAccountName")) -and (-not $PSBoundParameters.ContainsKey("ExcludeSamAccountName"))) { $EventData = " *[EventData[ Data[@Name='TargetUserName'] != 'SYSTEM' and Data[@Name='TargetUserName'] != '$($Computer)$' ] ] " } $Filter = @" <QueryList> <Query Id="0"> <Select Path="Security"> *[System[ Provider[@Name='Microsoft-Windows-Security-Auditing'] and EventID=$EventID and TimeCreated[timediff(@SystemTime) <= $($Time)] ] ] and $EventData </Select> </Query> </QueryList> "@ if ($PSBoundParameters.ContainsKey("Credential")) { $EventLogList = Get-WinEvent -ComputerName $Computer -FilterXml $Filter -Credential $Credential -ErrorAction Stop } else { $EventLogList = Get-WinEvent -ComputerName $Computer -FilterXml $Filter -ErrorAction Stop } $Output = foreach ($Log in $EventLogList) { #Removing seconds and milliseconds from timestamp as this is allow duplicate entries to be displayed $TimeStamp = $Log.timeCReated.ToString('MM/dd/yyyy hh:mm tt') -as [DateTime] switch ($Log.Properties[8].Value) { 2 {$LoginType = 'Interactive'} 3 {$LoginType = 'Network'} 4 {$LoginType = 'Batch'} 5 {$LoginType = 'Service'} 7 {$LoginType = 'Unlock'} 8 {$LoginType = 'NetworkCleartext'} 9 {$LoginType = 'NewCredentials'} 10 {$LoginType = 'RemoteInteractive'} 11 {$LoginType = 'CachedInteractive'} } if ($LoginEvent -eq 'FailedLogin') { $LoginType = 'FailedLogin' } if ($LoginEvent -eq 'DisconnectFromRDP') { $LoginType = 'DisconnectFromRDP' } if ($LoginEvent -eq 'Logoff') { $LoginType = 'Logoff' $UserName = $Log.Properties[1].Value.toLower() } else { $UserName = $Log.Properties[5].Value.toLower() } [PSCustomObject]@{ ComputerName = $Computer TimeStamp = $TimeStamp UserName = $UserName LoginType = $LoginType } } #Because of duplicate items, we'll append another select object to grab only unique objects $Output | select ComputerName, TimeStamp, UserName, LoginType -Unique | select -First $MaxEvents } catch { Write-Error $_.Exception.Message } } } END {} }
Now let’s see what kind of output we get when we run this script on a remote computer. This may take some time depending on the speed of the remote machine. While you have the ability to do more than one at a time but I would probably recommend only doing one a time because these are pretty noisy.
One item I would eventually want to fix is to consolidate the items that are created at the same time. Currently there is one entry for each individual event but that would take a bit more time and logic to construct.
Anwway, I hope you were able to find use in our Powershell script to get last logon user on computers. There are a ton of creative use cases and luckily the foundational code is available to use. Be sure to check out our own Powershell gallery for useful, real world scripts. Finally, don’t forget to check out our YouTube Channel where we post sysadmin content in video form. This get computer last login information using Powershell function has come in handy from time to time and wanted to share.
It will easy to undersatnd for single computer to fetch details, but for bulk list, it will need scripting.
In your blog post, write a on this topic too
Thanks. This works well. My only suggestion is to add filters for Interactive and RemoteInteractive. Would be nice to combine both. Reason: If you query a busy file server, there will be MANY network logons used to access the file shares. Most of the time, that is not what people are after. They want to know who actually logged onto the server (Interactive and RemoteInteractive). Easy to fix though. Thanks.
I keep getting RPC is unavailable:
“Get-LastLoginInfo : Could not retrieve information about the Security log. Error: The RPC server is unavailable.
At line:3 char:1
+ Get-LastLoginInfo -ComputerName”
Where you able to figure out why you were getting that error? I am getting the same thing.
Did anyone else cross this error or figured out a solution? I am experiencing the same error message.
Hi Paul, very nice work! Thx for the function. I have one problem with the function. Everytime I execute the function the field “TimeStamp” is empty. Any thoughts on this?