User Sessions

Published: Sep 11, 2022 by Bertland Hope

Calculates how long users were logged in based on audit events.

Requirements

  • Enable “Audit logon events” in Group Policy.
    • Windows Settings\Security Settings\Local Policies\Audit Policy
  • Configure your retention policy to keep the amount of history you want.
    • Administrative Templates\Windows Components\Event Log Service\Security

Parameters

Lowercase

Transforms the Username field to lowercase so it groups properly in Inventory. If you don’t want this behavior, remove -Lowercase from the Parameters field.

[CmdletBinding()]
param (
	[Switch]$Lowercase
)

$Logons = @{}
$LogonTypes = @{
	2  = 'Local'
	10 = 'Remote'
}
$IndexTable = @{
	4624 = @{
		'AccountName' = 5
		'LogonId'     = 7
	}
	4647 = @{
		'AccountName' = 1
		'LogonId'     = 3
	}
}
$Params = @{
	'LogName'     = 'Security'
	'InstanceId'  = [Array]$IndexTable.Keys
	'ErrorAction' = 'SilentlyContinue'
}

# Query all logon and logoff events.
Get-EventLog @Params | ForEach-Object {

	$EventMessage = $_
	$TimeGenerated = $EventMessage.TimeGenerated
	# InstanceId is Int64, but hashtable keys have to be Int32.
	$InstanceId = [Int32]$EventMessage.InstanceId
	$IndexData = $IndexTable.$InstanceId
	$AccountName = $EventMessage.ReplacementStrings[$IndexData.AccountName]
	$LogonId = $EventMessage.ReplacementStrings[$IndexData.LogonId]

	# Skip Windows service accounts.
	if ( $AccountName -match '^(DWM|UMFD)-\d' ) {

		Return

	}

	# Make usernames lowercase so they group properly in Inventory.
	if ( $Lowercase ) {

		$AccountName = $AccountName.ToLower()

	}

	switch ( $InstanceId ) {

		# Logoff.
		4647 {

			# Temporarily store the time and Id in a hashtable so it can be matched to its logon event.
			$Logons.$AccountName = @{
				'Time' = $TimeGenerated
				'Id'   = $LogonId
			}

		}

		# Logon.
		4624 {

			# Skip this logon event if there's no logoff event with a matching username.
			if ( -not $Logons.$AccountName ) {

				Return

			}

			$SessionData = $Logons.$AccountName

			# Skip logon events that don't match the logoff event's Logon ID.
			if ( $SessionData.Id -ne $LogonId ) {

				Return

			}

			$LogonType = [Int32]$EventMessage.ReplacementStrings[8]

			# Skip logon events that don't match the list of logon types.
			if ( $LogonType -notin $LogonTypes.Keys ) {

				Write-Verbose "Skipping ID $LogonId because it is Logon Type $LogonType"
				Return

			}
			
			$SessionLength = $SessionData.Time - $TimeGenerated
			$Logons.Remove($AccountName)

			[PSCustomObject]@{
				'Username'       = $AccountName
				'Logon Time'     = $TimeGenerated
				'Logoff Time'    = $SessionData.Time
				'Session Length' = $SessionLength
				'Logon Type'     = $LogonTypes.$LogonType
				'Logon ID'       = $LogonId
			} 

		}

	} 

}

Share

Latest News

10 Ways the ICT Performance Boost for Vision 2030 Jamaica Can Save You Money!
10 Ways the ICT Performance Boost for Vision 2030 Jamaica Can Save You Money!

10 Ways the ICT Performance Boost for Vision 2030 Jamaica Can Save You Money

What is a Constellation?
What is a Constellation?

What is a Constellation?

How are Pearls formed?
How are Pearls formed?

How are Pearls formed?

Chicken Back Gravy and Such Delights: Life Lessons From My Journey

Chicken Back Gravy and Such Delights: Life Lessons From My Journey

By Donna P. Hope

From $6.74

Inna Di Dancehall: Popular Culture And the Politics of Identity in Jamaica

Inna Di Dancehall: Popular Culture And the Politics of Identity in Jamaica

Donna P. Hope

From $22.96