Domain-Controllers monitor successful logon attempts by default. All events of all login attempts are logged in the Event Viewer. In this article I will cover how to monitor all logon events with PowerShell. Let’s dive in.
What is it about?
Successful logons are logged with ID 4624. Failed attempts are logged with ID 4771. Furthermore, we should also specify the user name.

Code Samples for successful and failed Logons
Successful Logons – 4624
The following code displays all successful logons of the username f.bizeps (Franz Bizeps) 😉
Get-EventLog -LogName Security -InstanceId 4624 |
Where-Object Message -match "f.bizeps" |
Format-Table TimeGenerated,Message -AutoSize -Wrap
A little bit more precise you can use Select-Object to display only the last logon.
Get-EventLog -LogName Security -InstanceId 4624 |
Where-Object Message -match "f.bizeps" |
Select-Object -First 1 |
Format-Table TimeGenerated,Message -AutoSize -Wrap

Failed Logons – 4771
Note that failed logons are not enabled by default. This setting must be enabled in the default domain controllers policy.
For showing all failed logons of user f.bizeps run the command below.
Get-EventLog -LogName Security -InstanceId 4771 |
Where-Object Message -match "f.bizeps" |
Format-Table TimeGenerated,Message -AutoSize -Wrap
Hope this was helpful!
Categories: Cyber Security, PowerShell
Patrick … and all interrested readers, I’ve done a personal memo about this in my github repo.
https://github.com/myusefulrepo/Tips/blob/master/Tips%20-%20How%20to%20use%20get-WinEvent%20efficiently.md
It’s just more “illustrated” and more complete than what I explained.
If this could help some people.
LikeLiked by 2 people
Thanks a lot! Bookmarked!
LikeLiked by 1 person
Hi Patrick,
Another way is to use Get-WinEvent and better Get-WinEvent with -FilterHashTable for better performance or a better later exploitability.
Let me show a sample, based on your search.
$Query = Get-WinEvent -FilterHashtable @{LogName = “Security”
Id = 4624}
$Query | Select-Object -Property @{Label = “TimeCreated” ; Expression = {$_.TimeCreated}},
@{Label = “ID” ; Expression = {$_.ID}},
@{Label = “MachineName” ; Expression = {$_.MachineName}},
@{Label = “LevelDisplayName” ; Expression = {$_.LevelDisplayName}},
@{Label = “TaskDisplayName” ; Expression = {$_.TaskDisplayName}},
@{Label = “SecurityId” ; Expression = {$_.Properties[4].Value}},
@{Label = “AccountName” ; Expression = {$_.Properties[5].Value}},
@{Label = “AccountDomain” ; Expression = {$_.Properties[6].Value}},
@{Label = “LogonId” ; Expression = {$_.Properties[7].Value}},
@{Label = “LogonType” ; Expression = {$_.Properties[8].Value}},
@{Label = “Workstation” ; Expression = {$_.Properties[11].Value}},
@{Label = “LogonGuid” ; Expression = {$_.Properties[12].Value}} |
Where-Object -Property AccountName -EQ “Olivier” |
Format-Table -AutoSize -Wrap
The output is displayed as an object, not a block string. It’s very boring with eventlogs, a lot of information are located in a unique property called Properties (corresponding to Message). With your previsious code, the output is just a string block for all the Message property.
In the FilterHasTable, you could also add other parameters like the folowwing, and there is very efficient.
$StartTime = Get-Date -Year 2020 -Month 10 -Day 7 -Hour 07 -Minute 36 -Second 02
$EndTime = Get-Date -Year 2020 -Month 10 -Day 7 -Hour 07 -Minute 36 -Second 05
$Query = Get-WinEvent -FilterHashtable @{
LogName = ‘Security’
StartTime = $StartTime
EndTime = $EndTime
ID = “4624”
}
Nota : I separate the EventLog query from the display. The query takes the longest time. You could also reduced easily the query by Adding the parameter -MaxEvents
I recognize, however, that in the case showed, Get-EventLog is quite effective.-
LikeLiked by 2 people
Thank you!
LikeLiked by 1 person