Stack Overflow Asked by Jeremiah Williams on January 5, 2022
I’m working on a Powershell script to get all users who have logged in/out of a server in the past 7 days, where their name is not like "*-organization". The below works, but no matter what I try I’m not able to filter names
$logs = get-eventlog system -ComputerName $env:computername -source Microsoft-Windows-Winlogon -After (Get-Date).AddDays(-7)
$res = @()
ForEach ($log in $logs)
{
if($log.instanceid -eq 7001){
$type = "Logon"
}
Elseif ($log.instanceid -eq 7002){
$type = "Logoff"
}
Else { Continue }
$res += New-Object PSObject -Property @{Time = $log.TimeWritten; "Event" = $type; User = (New-Object System.Security.Principal.SecurityIdentifier $Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])}};
$res
I’ve tried adding this line in various places and ways, but no matter what I can’t get it to filter. It either fails and tells me my operator must have a property and value, or it runs fine and ignores any username filtering.
| Where-Object $_.User -notlike "*-organization"
Is it even possible to filter the login username with this method? If so, what am I doing wrong? If it’s not possible, is there another way I can get what I need?
You can do this with the -FilterXPath
parameter like below:
$filter = "(*[System/EventID=7001] or *[System/EventID=7002]) and *[System/Provider[@Name='Microsoft-Windows-Winlogon']]"
$result = Get-WinEvent -LogName System -FilterXPath $filter | ForEach-Object {
# convert the event to XML and grab the Event node
$eventXml = ([xml]$_.ToXml()).Event
$eventData = $eventXml.EventData.Data
$userSID = ($eventData | Where-Object { $_.Name -eq 'UserSid' }).'#text'
$userName = [System.Security.Principal.SecurityIdentifier]::new($userSID).Translate([System.Security.Principal.NTAccount])
# you can add username filtering here if you like.
# remember the $userName is in formal DOMAINLOGONNAME
# if ($username -notlike "*-organization") {
# output the properties you need
[PSCustomObject]@{
Time = [DateTime]$eventXml.System.TimeCreated.SystemTime
Event = if ($eventXml.System.EventID -eq 7001) { 'LogOn' } else { 'LogOff' }
UserName = $userName
UserSID = $userSID
Computer = $eventXml.System.Computer
}
# }
}
# output on screen
$result
# output to CSV file
$result | Export-Csv -Path 'X:TheOutputFile.csv' -NoTypeInformation
Note, I have commented out the username filtering in the code. It is just there to give you an idea of where to put it. Of course, you can also filter the $result
afterwards:
$result | Where-Object { $_.UserName -notlike "*-organization" }
Answered by Theo on January 5, 2022
Adding to @js2010's helpful answer, and with the assumption you're using PowerShell 5.1. I usually identify the property array index and use Select-Object
to create a custom property as needed.
$WinEvents =
get-winevent @{logname='system'; providername='Microsoft-Windows-Winlogon'} |
Select-Object @{Name = 'Time'; Expression = {$_.TimeCreated}},
@{Name = 'Event'; Expression = { If($_.ID -eq 7001){'Logon'} ElseIf($_.ID -eq 7002){ 'Logoff' } } },
@{Name = 'User'; Expression = { [System.Security.Principal.SecurityIdentifier]::new( $_.Properties[1].Value ).Translate([System.Security.Principal.NTAccount]) } }
In your case this should add a property called User with a value like DomainNameUserName to the objects. I also added expressions to derive the other properties you were adding to your custom objects. Select-Object
emits custom objects as well so this should give the result you're looking for.
Let me know if this helps.
Update
Respectfully, the other 2 answers make the assumption that you are looking for logon/off events for a specific user. That's not how I read the question; in particular:
"get all users who have logged in/out of a server"
While PowerShell 7+ does let you directly cite UserID in the FilterHashtable, it's not very useful here because we're not seeking events for a specific user. Furthermore, it seems unhelpful for the ultimate output as by default it echoes as a SID. It would still need to be translated, not only for display but for further filtering. I'm also not positive that UserID will always be the same as Properties[1]
, there's certainly some variance when looking at other event IDs.
The XML work is very cool, but I don't think it's called for here.
There were some issues with my answer as well. I overlooked filtering the event IDs & dates up front. I also realized we don't need to instantiate [System.Security.Principal.SecurityIdentifier]
class because the property is already typed as such. Along with some readability improvements I corrected those issues below.
# Should be the 1st line!
using NameSpace System.Security.Principal
$ResolveEventType = @{ 7001 = 'Logon'; 7002 = 'Logoff' }
$FilterHashTable =
@{
LogName = 'system'
ProviderName = 'Microsoft-Windows-Winlogon'
ID = 7001,7002
StartTime = (Get-Date).AddDays(-7)
}
[Array]$WinEvents =
Get-WinEvent -FilterHashtable $FilterHashTable |
Select-Object @{ Name = 'Time'; Expression = { $_.TimeCreated } },
@{ Name = 'Event'; Expression = { $ResolveEventType[ $_.ID ] } },
@{ Name = 'User'; Expression = { $_.Properties[1].Value.Translate( [NTAccount] ) } }
$WinEvents |
Where-Object{ $_.UserName -notlike "*-organization" } |
Format-Table -AutoSize
This tested good in PowerShell 5.1 & 7.0. I added Format-Table
to display the output, but you can just change that out for an Export-Csv
command as needed
Note: The last 2 pipelines can be combined, but I thought this was a little more readable.
Let me know if this helps.
Answered by Steven on January 5, 2022
There would have to be a property named 'user' for that to work. Get-eventlog is actually obsolete now, and replaced by get-winevent. Unfortunately, you have to get into the xml to filter by usersid. I've included a time filter.
$a = get-winevent @{logname='system';
providername='Microsoft-Windows-Winlogon'} -MaxEvents 1
$e = $a.ToXml() -as 'xml'
$e.event.EventData
Data
----
{TSId, UserSid}
get-winevent @{logname='system';providername='Microsoft-Windows-Winlogon';
data='S-2-6-31-1528843147-473324174-2919417754-2001';starttime=(Get-Date).AddDays(-7);
id=7001,7002}
In powershell 7 you can refer to the eventdata named data fields directly:
get-winevent @{logname='system';providername='Microsoft-Windows-Winlogon';
usersid='S-2-6-31-1528843147-473324174-2919417754-2001'}
The get-winevent docs say you can use "userid" in the filterhashtable, but I can't get that to work.
EDIT: Actually this works. But without limiting it too much, at least for me.
get-winevent @{logname='system';userid='js2010'}
get-winevent @{providername='Microsoft-Windows-Winlogon';userid='js2010'}
Answered by js2010 on January 5, 2022
1 Asked on November 28, 2020 by niko-gamulin
7 Asked on November 27, 2020 by galsuchetzky
2 Asked on November 27, 2020 by mohamed-rady
4 Asked on November 27, 2020 by jithin
1 Asked on November 27, 2020 by tuna-ariyurek
1 Asked on November 27, 2020 by hellow
1 Asked on November 27, 2020 by ricardo-mrquez
asp net core mvc authentication azure azure active directory c
2 Asked on November 27, 2020 by dogukanakgol
1 Asked on November 27, 2020 by tjdillashaw
3 Asked on November 26, 2020 by sean-urbassik
1 Asked on November 26, 2020 by jacob-steenhuysen
2 Asked on November 26, 2020 by ale_aalt
0 Asked on November 26, 2020 by user14537181
1 Asked on November 26, 2020 by uthpala-dl
3 Asked on November 26, 2020
8 Asked on November 26, 2020 by eddev
1 Asked on November 26, 2020 by user3476509
0 Asked on November 26, 2020 by kad
signaling spring boot spring data jpa spring websocket webrtc
14 Asked on November 26, 2020 by eliko
Get help from others!
Recent Answers
Recent Questions
© 2023 AnswerBun.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP