How does one read logon and logoff events from the Windows event log, and retrieve the corresponding information for each user from Active Directory, using Powershell?
Asked
Active
Viewed 9,059 times
3
-
Why post a question if you are not looking for an answer??? – lucianomarisi May 22 '14 at 15:11
-
So if someone else wants to ask it, the answer is already there. – Autumn Baril May 22 '14 at 15:29
-
@AutumnBaril I found your question and answer to be beneficial and have +1 the question. – Colyn1337 May 22 '14 at 17:49
2 Answers
6
The following script will read Winlogon events from the System log, retrieve information from AD based on each user's SID, and display the results in a generated HTML page. The results of each AD lookup are cached to prevent unnecessary round-trips to the AD server.
# event id 7001 is Logon, event id 7002 is Logoff
function WinlogonEventIdToString($EventID) {switch($EventID){7001{"Logon";break}7002{"Logoff";break}}}
# look up SID in Active Directory and cache the results in a hashtable
$AdUsers = @{}
function SidToAdUser($sid) {
$AdUser = $AdUsers[$sid]
if ($AdUser -eq $null) {
$AdUser = $AdUsers[$sid] = [adsi]("LDAP://<SID=" + $sid + ">")
}
return $AdUser
}
$outputFilename = [System.IO.Path]::GetTempPath() + "DisplayLatestLogonEvents.html"
# the first Select extracts the SID from the event log entry and converts the event id to a descriptive string
# the second Select is responsible for looking up the User object in Active Directory, using the SID
# the final Select picks the various attribute data from the User object, ready for display in the table
# to retrieve only recent log entries, one can use something like this in Get-EventLog: -After (Get-Date).AddDays(-14)
Get-Eventlog -Logname "System" -Source "Microsoft-Windows-Winlogon" -InstanceId 7001,7002 `
| Select TimeGenerated, @{n='Operation';e={WinlogonEventIdToString $_.EventID}}, @{n='SID';e={$_.ReplacementStrings[1]}} `
| Select TimeGenerated, Operation, @{n='AdUser';e={(SidToAdUser $_.SID)}} `
| Select TimeGenerated, Operation, `
@{n='Username';e={$_.AdUser.sAMAccountName}}, `
@{n='Full name';e={$_.AdUser.firstname + " " + $_.AdUser.lastname}}, `
@{n='Title';e={$_.AdUser.title}}, `
@{n='Department';e={$_.AdUser.department}}, `
@{n='Company';e={$_.AdUser.company}} `
| ConvertTo-HTML -Head "<style>td, th { border:1px solid grey }</style>" | Out-File $outputFilename
# this will open the default web browser
Invoke-Expression $outputFilename

Autumn Baril
- 101
- 1
- 6
0
With Windows 10 professional, a member of Active Directory domain, this script will generate a list of logon / logoff times for the selected user, includes events from screensaver lockscreen. Powershell script to log active work hours, no application needed.
# original source: https://community.spiceworks.com/topic/764481-get-logon-off-workstation-lock-unlock-times
# cleaned up, filtered by username, and included lock by screensaver timeout by kevin, Dec 2018
# must enable auditing via secpol.msc
# Security Settings -> Advanced Audit Policy -> System Audit -> Logon/Logoff -> Audit Other Logon/Off Events -> On Success
$days = 30
$username = "kevin"
Write-Host "Retrieving last $days days of user: $username, logon/logoff activity... please wait
$events = @()
$events += Get-WinEvent -FilterHashtable @{
LogName='Security'
Id=@(4624,4800,4634)
StartTime=(Get-Date).AddDays(-$days)
}
$type_lu = @{
4624 = 'Logon'
4800 = 'Logoff' # screensaver lock
4634 = 'Logoff' # explicit
}
$ns = @{'ns'='http://schemas.microsoft.com/win/2004/08/events/event'}
$target_xpath = "//ns:Data[@Name='TargetUserName']"
$usersid_xpath = "//ns:Data[@Name='UserSid']"
If($events) {
$results = ForEach($event in $events) {
$xml = $event.ToXml()
Switch -Regex ($event.Id) {
'4...' {
$user = (
Select-Xml -Content $xml -Namespace $ns -XPath $target_xpath
).Node.'#text'
Break
}
'7...' {
$sid = (
Select-Xml -Content $xml -Namespace $ns -XPath $usersid_xpath
).Node.'#text'
$user = (
New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList $sid
).Translate([System.Security.Principal.NTAccount]).Value
Break
}
}
if($username -eq $user) {
New-Object -TypeName PSObject -Property @{
Time = $event.TimeCreated
Id = $event.Id
Type = $type_lu[$event.Id]
User = $user
}
}
}
If($results) {
$results
}
}
Example output:
C:\WINDOWS\system32>powershell -file C:\desk\path\timetracker.ps1
Retrieving last 10 days of user: kevin, logon/logoff activity
Time User Id Type
---- ---- -- ----
12/4/2018 1:39:22 PM kevin 4634 Logoff
12/4/2018 1:39:19 PM kevin 4800 Logoff
12/4/2018 1:10:28 PM kevin 4634 Logoff
12/4/2018 1:10:28 PM kevin 4624 Logon
12/4/2018 12:57:32 PM kevin 4634 Logoff
12/4/2018 12:57:32 PM kevin 4624 Logon
12/4/2018 12:29:43 PM kevin 4624 Logon
12/4/2018 11:48:11 AM kevin 4634 Logoff
To debug this script, I opened Event Viewer eventvwr.msc, and used this custom filter (XML).
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">*[System[(EventID=4624)] and EventData[Data[@Name='TargetUserName']='kevin']]</Select>
</Query>
</QueryList>
Powershell also has Get-EventLog cmdlet, but I found it lacking in options.

Kevin
- 2,761
- 1
- 27
- 31