Login History Domain Member Server

Hello,
first of all I am a complete Powershell beginner.
And have found only approaches to my concern but no concrete solution.
I would like to display the login history (successful logins) of the last 2 months for all users on a certain domain member server. Failed logins should not appear.

I would be very happy about a solution and it would also be a great learning effect for me.
Many thanks in advance
Best greetings

Powernoob,
Welcome to the forum. :wave:t4:

My first idea would be to parse the according eventlogs for the related events. But …

This forum is for scripting questions rather than script requests. We do not write customized and ready to use scripts or solutions on request.

We actually expect you to make an own attempt at the first place to get your task done or to solve your problem. If you have done so already please document here what exactly you have done and show your code. Then we probably might be able to help you step further.

Here is my first draft.
But how to use it to query the domain with username and login history. No idea.
Get-EventLog System -Source Microsoft-Windows-WinLogon -After (Get-Date).AddDays(-180) -ComputerName $env:computername > C:\Logfiles\Test\An_Abmeldelogs.txt

… I would run the script on the member server in question. Or does it have to run on the DC?

To the best of my knowledge, the log you have chosen will not get you what you want. You would need to parse the Security log for specific events. This is what I use. Since your original code specifies a specific log on a specific system, this does the same:

$SuccessLoginsFilter = "(Event[System[EventID=4624 or EventID=4648]]) and (Event[EventData[Data[@Name='LogonType'] = '2']] or Event[EventData[Data[@Name='LogonType'] = '3']] or Event[EventData[Data[@Name='LogonType'] = '7']] or Event[EventData[Data[@Name='LogonType'] = '10']] or Event[EventData[Data[@Name='LogonType'] = '11']]) and (Event[EventData[Data[@Name='SubjectUserSid'] != 'S-1-0-0']])"

Get-WinEvent -Path 'C:\Windows\System32\winevt\logs\security.evtx' -FilterXPath $SuccessLoginsFilter | Where-Object {$_.TimeCreated -ge (Get-Date).AddDays(-180)}

Hopefully, this will get you started. You could also get tons of examples via a google search.

Since I actually started this answer before @tonyd and just got distracted with work I will post it anyway. Especially because it shows a different approach.

And since you’re a beginner you probably wouldn’t learn much when I simply provide the working code … :wink: … so let’s do it step by step.

First of all … when you post code, sample data, console output or error messages please format it as code using the preformatted text button ( </> ). Simply place your cursor on an empty line, click the button and paste your code.

Thanks in advance

How to format code in PowerShell.org <---- Click :point_up_2:t4: :wink:

Second … don’t use Get-Eventlog anymore. Instead use

I’d receommend to use a filter hashtable since it is easy to read and maintain. I’m unsure if you picked the right eventlog but let’s use it for now for the first steps just to show how it may work:

$FilterHashtable = @{
    logname      = 'Microsoft-Windows-Winlogon/Operational'
    StartTime    = (Get-Date).Date.AddDays(-180)
    EndTime      = (Get-Date).Date
}

Now we query the eventlog and limit the output to maybe 20 for now … just to see what we will get and be able to pick what’s useful for us …

Get-WinEvent -FilterHashtable $FilterHashtable -MaxEvents 20 | 
    Select-Object -Property *

Now you should inspect the output and figure out what properties you need. It may be enough to get events with the Id of 812 since we don’t need two return values per event … I guess. So we modify our hashtable like this:

$FilterHashtable = @{
    logname   = 'Microsoft-Windows-Winlogon/Operational'
    StartTime = (Get-Date).Date.AddDays(-180)
    EndTime   = (Get-Date).Date
    Id        = 812
}

Running the query again I noticed that we have some local accounts as well. I’d assume you don’t need them, right? So we get rid of them with a

Get-WinEvent -FilterHashtable $FilterHashtable -MaxEvents 20 | 
    Where-Object {$_.UserId.ToString().length -gt 8} |
        Select-Object -Property UserId, TimeCreated

Now you just need to translate the SIDs into names. In order not to have to query the AD again and again, you should do this beforehand. And to easily translate the SID into the sAMAccountName we can use a hashtable.

$UserHashtable = @{}
$SearchBase = 'OU=Berlin,OU=Germany,OU=Europe,DC=contoso,DC=com'
Get-ADUser -Filter "enabled -eq 'true'" -SearchBase $SearchBase |
    ForEach-Object {
        $UserHashtable.add($_.SID.Value, $_.sAMAccountName)
    }

Now we can use this hashtable in a calculated property …

Get-WinEvent -FilterHashtable $FilterHashtable | 
    Where-Object {$_.UserId.ToString().length -gt 8} |
        Select-Object -Property UserId, TimeCreated, 
                @{Name = 'UserName'; Expression = {$UserHashtable[$_.UserId.Value]}}

This should give you an idea of how to approach a task like this.

A general tip at the end: You should always read the help for the cmdlets you’re about to use COMPLETELY INCLUDING THE EXAMPLES to learn how to use them. :point_up_2:t4: :wink:

Thanks Olaf, sorry for butting in :frowning:

No need to sorry at all. That’s we’re all here for, isn’t it? :wink:

Thank you very much for the very helpful answers. :+1: :+1: :+1:
I will try to implement it accordingly.
In any case, very helpful for me as a beginner and an important foundation to further expand my knowledge.
Kind regards