---
title: "Finding PowerShell Last Logon by User Logon Event ID"
description: "Learn how to build a user activity PowerShell last logon script that will pull the user logon event ID."
canonical: "https://adamtheautomator.com/user-logon-event-id/"
---

# Finding PowerShell Last Logon by User Logon Event ID

> Learn how to build a user activity PowerShell last logon script that will pull the user logon event ID.

Source: https://adamtheautomator.com/user-logon-event-id/

---

ATA Learning

Tap to hide

[

ATA Learning

](/)

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Search for:  

*   [](https://twitter.com/adbertram)
*   [](https://github.com/Adam-the-Automator)
*   [](https://www.linkedin.com/company/adam-the-automator-llc)
*   [](/feed/)

![Finding PowerShell Last Logon by User Logon Event ID](https://adamtheautomator.com/wp-content/uploads/2019/06/photo-1516382799247-87df95d790b7.jpg)

# Finding PowerShell Last Logon by User Logon Event ID

[![](https://secure.gravatar.com/avatar/d0b9d42e21e5622713f8b693aa5c0f9244d5f7dd200ed29b8398f52dee5de337?s=192&d=mm&r=g)Adam Bertram](https://adamtheautomator.com/author/adam-bertram/)3 December 20216 min. read

Categories: [IT Ops](/category/it-ops/)

Tags:[PowerShell](/tag/powershell/)[Windows 10](/tag/windows-10/)[windows server](/tag/windows-server/)

Table of Contents

*   [Prerequisites](#prerequisites)
*   [Enabling Audit Policies](#enabling-audit-policies)
*   [Understanding User Logon Sessions and PowerShell Last Logon](#understanding-user-logon-sessions)
*   [The User Login History Script](#the-user-login-history-script)

There are many fancy tools out there to monitor user login activity. What if I told you, you didn’t need to spend any money by building a PowerShell last logon and history script? You can find the last logon date and even the user logon event ID with the Windows event log and a little PowerShell!

Not a reader? Watch this related video tutorial!

**_Not seeing the video? Make sure your ad blocker is disabled._**

In this article, you’re going to learn how to build a user activity [PowerShell](https://adamtheautomator.com/tag/powershell/) script. This script will pull information from the Windows event log for a local computer and provide a detailed report on user login activity like finding PowerShell last logon.

> Meet AD and Windows Server auditing, security, and compliance needs with ManageEngine ADAudit Plus. [Download Free Trail!](https://www.manageengine.com/products/active-directory-audit/sem/tp/active-directory-auditing.html?utm_source=ATA&utm_medium=website-listing&utm_campaign=adap-last_logon)

## Prerequisites

If you’re in an AD environment be sure you:

*   are on a domain-joined [Windows 10](https://adamtheautomator.com/tag/windows-10/) PC
*   are logged in with an account that can read domain controller event logs
*   have permission to modify domain GPOs

> _Audit policies to enable login auditing will be set via GPO in this article. But you can use local policies instead._

## Enabling Audit Policies

To ensure the event log on the computer records user logins like recording the PowerShell last logon, you must first enable some audit policies. In this article, you’ll learn how to set these policies via GPO. But if you don’t have AD, you can also set these same policies via local policy.

To report on the time users have been logged in, you’ll first need to enable three advanced audit policies.

*   _Audit Logoff – When a user is logged off._
*   _Audit Logon – When a user authenticates to Windows_
*   _Audit Other Logon/Logoff Events – Computer lock, unlocks, RDP connects and disconnects_

Enabling all of these audit policies ensures you capture all possible activity start and stop times.

When you enable these audit policies on a local PC, the following user logon time event IDs (and logoff IDs) will begin to be recorded in the Windows event logs to enable finding via PowerShell last logon events. Each of these events represents a user activity start and stop time.

*   Logon – ****4624****
*   Logoff – ****4647****
*   Startup – ****6005****
*   RDP Session Reconnect – ****4778****
*   RDP Session Disconnect – ****4779****
*   Locked – ****4800****
*   Unlocked – ****4801****

You can see an example below of modifying the _Default Domain Policy_ GPO. You’d modify this GPO if enabling these policies on all domain-joined PCs. You may also create your own auditing policy GPO and assign it to various OUs as well.

![Enabling the Audit Logoff, Audit Logon and Audit Other Logon/Logoff Events policies](https://adamtheautomator.com/wp-content/uploads/2016/01/Logon1.png)

Enabling the Audit Logoff, Audit Logon and Audit Other Logon/Logoff Events policies

## Understanding User Logon Sessions and PowerShell Last Logon

Once all of the appropriate events are being generated, you’ve now got to define user login sessions. I’m calling a user session as the total time between when the user begins working and stops; that’s it. To build an accurate report, the script must match up the start and end times to understand these PowerShell last logon sessions.

The concept of a logon session is important because there might be more than one user logging onto a computer. To match up start/stop times with a particular user account, you can use the `Logon ID` field for each event.

To figure out the start and stop times of a login session, the script finds a session start time and looks back through the event log for the next session stop time with the same Logon ID. Once that event is found (the stop event), the script then knows the user’s total session time.

You can see an example of an event viewer user logon event id (and logoff) with the same `Logon ID` below.

![PowerShell Last Logon : Login event ID in event view](https://adamtheautomator.com/wp-content/uploads/2016/01/Logon2.png)

PowerShell Last Logon : Login event ID in event view

![Login event ID in event view](https://adamtheautomator.com/wp-content/uploads/2016/01/Logon3.png)

Login event ID in event view

In this example, the _LAB\\Administrator_ account had logged in (ID 4624) on 8/27/2015 at 5:28PM with a Logon ID of _0x146FF6_. By searching earlier in the event log, a session end event (ID 4634) was found with the same Logon ID at 5:30PM on the same day. By now knowing the start time and stop time for this particular login session, you can then deduce that the _LAB\\Administrator_ account had been logged on for three minutes or so.

> Meet AD and Windows Server auditing, security, and compliance needs with ManageEngine ADAudit Plus. [Download Free Trail!](https://www.manageengine.com/products/active-directory-audit/sem/tp/active-directory-auditing.html?utm_source=ATA&utm_medium=website-listing&utm_campaign=adap-last_logon)

## The User Login History Script

Once the policies are enabled and you understand the concept of a login session, you can then start writing some PowerShell to find PowerShell last logon events.

Rather than going over this script line by line, it is provided in its entirety below. You can also download it from [this GitHub repo](https://github.com/adbertram/Random-PowerShell-Work/blob/master/ActiveDirectory/Get-UserLogonSessionHistory.ps1).

In summary, the script below:

1.  Defines all of the important start and stop event ID necessary for PowerShell last logon events.
2.  Creates an XPath query to find appropriate events.
3.  Queries each computer using XPath event log query.
4.  Finds the start event IDs and attempts to match them up to stop event IDs.
5.  Outputs start/end times with other information.

> _Note: This script may need some tweaks to work 100% correctly. Please issue a GitHub pull request if you notice problems and would like to fix them._

```powershell
<#	
.SYNOPSIS
	This script finds all PowerShell last logon, logoff and total active session times of all users on all computers specified. For this script
	to function as expected, the advanced AD policies; Audit Logon, Audit Logoff and Audit Other Logon/Logoff Events must be
    enabled and targeted to the appropriate computers via GPO or local policy.
.EXAMPLE
	
.PARAMETER ComputerName
	An array of computer names to search for events on. If this is not provided, the script will search the local computer.
.INPUTS
	None. You cannot pipe objects to Get-ActiveDirectoryUserActivity.ps1.
.OUTPUTS
	None. If successful, this script does not output anything.
#>
[CmdletBinding()]
param
(
    [Parameter()]
    [ValidateNotNullOrEmpty()]
    [string[]]$ComputerName = $Env:COMPUTERNAME
)

try {
	
    #region Defie all of the events to indicate session start or top
    $sessionEvents = @(
        @{ 'Label' = 'Logon'; 'EventType' = 'SessionStart'; 'LogName' = 'Security'; 'ID' = 4624 } ## Advanced Audit Policy --> Audit Logon
        @{ 'Label' = 'Logoff'; 'EventType' = 'SessionStop'; 'LogName' = 'Security'; 'ID' = 4647 } ## Advanced Audit Policy --> Audit Logoff
        @{ 'Label' = 'Startup'; 'EventType' = 'SessionStop'; 'LogName' = 'System'; 'ID' = 6005 }
        @{ 'Label' = 'RdpSessionReconnect'; 'EventType' = 'SessionStart'; 'LogName' = 'Security'; 'ID' = 4778 } ## Advanced Audit Policy --> Audit Other Logon/Logoff Events
        @{ 'Label' = 'RdpSessionDisconnect'; 'EventType' = 'SessionStop'; 'LogName' = 'Security'; 'ID' = 4779 } ## Advanced Audit Policy --> Audit Other Logon/Logoff Events
        @{ 'Label' = 'Locked'; 'EventType' = 'SessionStop'; 'LogName' = 'Security'; 'ID' = 4800 } ## Advanced Audit Policy --> Audit Other Logon/Logoff Events
        @{ 'Label' = 'Unlocked'; 'EventType' = 'SessionStart'; 'LogName' = 'Security'; 'ID' = 4801 } ## Advanced Audit Policy --> Audit Other Logon/Logoff Events
    )
    
    ## All of the IDs that designate when user activity starts
    $sessionStartIds = ($sessionEvents | where { $_.EventType -eq 'SessionStart' }).ID
    ## All of the IDs that designate when user activity stops
    $sessionStopIds = ($sessionEvents | where { $_.EventType -eq 'SessionStop' }).ID
    #endregion
	
    ## Define all of the log names we'll be querying
    $logNames = ($sessionEvents.LogName | select -Unique)
    ## Grab all of the interesting IDs we'll be looking for
    $ids = $sessionEvents.Id
		
    ## Build the insane XPath query for the security event log in order to query PowerShell last logon events and others as fast as possible
    $logonXPath = "Event[System[EventID=4624]] and Event[EventData[Data[@Name='TargetDomainName'] != 'Window Manager']] and Event[EventData[Data[@Name='TargetDomainName'] != 'NT AUTHORITY']] and (Event[EventData[Data[@Name='LogonType'] = '2']] or Event[EventData[Data[@Name='LogonType'] = '10']])"
    $otherXpath = 'Event[System[({0})]]' -f "EventID=$(($ids.where({ $_ -ne '4624' })) -join ' or EventID=')"
    $xPath = '({0}) or ({1})' -f $logonXPath, $otherXpath

    foreach ($computer in $ComputerName) {
        ## Query each computer's event logs using the Xpath filter
        $events = Get-WinEvent -ComputerName $computer -LogName $logNames -FilterXPath $xPath
        Write-Verbose -Message "Found [$($events.Count)] events to look through"

        ## Set up the output object
        $output = [ordered]@{
            'ComputerName'          = $computer
            'Username'              = $null
            'StartTime'             = $null
            'StartAction'           = $null
            'StopTime'              = $null
            'StopAction'            = $null
            'Session Active (Days)' = $null
            'Session Active (Min)'  = $null
        }
        
        ## Need current users because if no stop time, they're still probably logged in
        $getGimInstanceParams = @{
            ClassName = 'Win32_ComputerSystem'
        }
        if ($computer -ne $Env:COMPUTERNAME) {
            $getGimInstanceParams.ComputerName = $computer
        }
        $loggedInUsers = Get-CimInstance @getGimInstanceParams | Select-Object -ExpandProperty UserName | foreach { $_.split('\')[1] }
            
        ## Find all user start activity events and begin parsing
        $events.where({ $_.Id -in $sessionStartIds }).foreach({
                try {
                    $logonEvtId = $_.Id
                    $output.StartAction = $sessionEvents.where({ $_.ID -eq $logonEvtId }).Label
                    $xEvt = [xml]$_.ToXml()

                    ## Figure out the login session ID
                    $output.Username = ($xEvt.Event.EventData.Data | where { $_.Name -eq 'TargetUserName' }).'#text'
                    $logonId = ($xEvt.Event.EventData.Data | where { $_.Name -eq 'TargetLogonId' }).'#text'
                    if (-not $logonId) {
                        $logonId = ($xEvt.Event.EventData.Data | where { $_.Name -eq 'LogonId' }).'#text'
                    }
                    $output.StartTime = $_.TimeCreated
        
                    Write-Verbose -Message "New session start event found: event ID [$($logonEvtId)] username [$($output.Username)] logonID [$($logonId)] time [$($output.StartTime)]"
                    ## Try to match up the user activity end event with the start event we're processing
                    if (-not ($sessionEndEvent = $Events.where({ ## If a user activity end event could not be found, assume the user is still logged on
                                    $_.TimeCreated -gt $output.StartTime -and
                                    $_.ID -in $sessionStopIds -and
                                    (([xml]$_.ToXml()).Event.EventData.Data | where { $_.Name -eq 'TargetLogonId' }).'#text' -eq $logonId
                                })) | select -last 1) {
                        if ($output.UserName -in $loggedInUsers) {
                            $output.StopTime = Get-Date
                            $output.StopAction = 'Still logged in'
                        } else {
                            throw "Could not find a session end event for logon ID [$($logonId)]."
                        }
                    } else {
                        ## Capture the user activity end time
                        $output.StopTime = $sessionEndEvent.TimeCreated
                        Write-Verbose -Message "Session stop ID is [$($sessionEndEvent.Id)]"
                        $output.StopAction = $sessionEvents.where({ $_.ID -eq $sessionEndEvent.Id }).Label
                    }

                    $sessionTimespan = New-TimeSpan -Start $output.StartTime -End $output.StopTime
                    $output.'Session Active (Days)' = [math]::Round($sessionTimespan.TotalDays, 2)
                    $output.'Session Active (Min)'  = [math]::Round($sessionTimespan.TotalMinutes, 2)
                    
                    [pscustomobject]$output
                } catch {
                    Write-Warning -Message $_.Exception.Message
                }
            })
    }
} catch {
    $PSCmdlet.ThrowTerminatingError($_)
}
```

Share this article

[Share on X](https://twitter.com/intent/tweet?url=https%3A%2F%2Fadamtheautomator.com%2Fuser-logon-event-id%2F&text=Finding%20PowerShell%20Last%20Logon%20by%20User%20Logon%20Event%20ID)[Share on Facebook](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fadamtheautomator.com%2Fuser-logon-event-id%2F)[Share on LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fadamtheautomator.com%2Fuser-logon-event-id%2F)

## Related Posts

![](https://adamtheautomator.com/wp-content/uploads/2021/02/How-to-Create-Checksums-in-Windows-Built-in-and-Third-Party-Tools.jpg)

### [Create Checksum in Windows and Verify File Integrity](/checksum-windows/)

Learn in this in-depth article that covers nearly all the ways to generate checksums in Windows using built-in and third-party tools.

![](https://adamtheautomator.com/wp-content/uploads/2026/06/26995-troubleshoot-dns-issues-powershell-codex.webp)

### [Troubleshoot DNS Issues with PowerShell](/troubleshoot-dns-issues-powershell/)

Troubleshoot DNS issues with PowerShell by testing name resolution, DNS client settings, cache entries, and network connectivity in a repeatable workflow.

![](https://adamtheautomator.com/wp-content/uploads/2024/01/OpenSSL-on-Windows-10.jpg)

### [Master OpenSSL on Windows 10: A Guide to Powerful Security](/openssl-windows-10/)

Master OpenSSL on Windows 10 with PowerShell, from installation to certificate signing requests and conversions.

## Categories

*   [IT Ops](/category/it-ops/)
*   [Cloud](/category/cloud/)
*   [DevOps](/category/devops/)
*   [Home Ops](/category/home-ops/)
*   [Information Security](/category/infosec/)
*   [Software Development](/category/software-development/)

## Site

*   [Home](/)
*   [Tutorials](/tutorials/)
*   [Instructors](/author/)
*   [Advertising](/advertising/)
*   [Recommended Resources](/resources/)
*   [About Adam](/about-adam/)

Copyright 2026© ATA Learning | [Privacy Policy](/privacy/)
