Fetch last 3 users logged in on each server on serverlist


I need some powershell help with a special custom PS1 script.

I have a list.txt of 225 servers (OS 2003, 2008 and 2012) and I want to find and get the last 3 domain users who have logged in on these servers. I have both hostname and IP on all the servers.

This is due to a task, where I need to find a system-owner on each server which nobody knows what is used for, and i would like to find some clues in the last 3 users logged in, to have something to go on from there.

Can anybody help me with this?

I am a domain admin on the serverdomain and admin on all the servers.

The servers are also running SCCM Agent, so I been thinking the information could maybe be fetched through the agents running on the servers?

I would apppreciate if anyone outthere could help on this one. :slight_smile:

Best regards
Brian P

You should be able to use Get-WinEvent and filter on the Security log for 4624 events and go from there

Shameless plug for my script on technet

SCCM tracks the user logon’s but does not give you a history of logon’s per system. But it does have device affinity reports that will give the primary(top) user of a system.

Hi Jonathan,

Thx for the reply. I read the script and understand what i does, but i am no where near a powershell coder, so i really dont know what to do to make this script and fetch the information and output it in a txt of exls file.

Could you help me make the script? I would gladly send a appreciation amount on paypal to you or those WHO can help me with this.

Best regards
Brian P

$Computername = "."
$return = Get-EventLog -LogName Security -ComputerName $Computername -InstanceId 4624
Write-Output "Logon Type 2 - interactive"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 2}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 3 - network"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 3}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 4 - batch"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 4}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 5 - service"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 5}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 7 - unlock"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 7}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 8 - networkceartext"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 8}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 9 - newcredentials (Runas)"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 9}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 10 - remoteinteractive"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 10}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
Write-Output "Logon Type 11 - cachedinteractive"
$return|Where-Object -FilterScript{$_.replacementstrings[8] -eq 11}|foreach-object{$_.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending

$computername = “.” - This is the computer name of the system to collect logon information. The period is a shortcut for local system. You can replace it with the remote computer’s name
$return = Get-EventLog -LogName Security -ComputerName $Computername -InstanceId 4624 - This collects all of the event id 4624 records.
Write-Output “Logon Type 2 - interactive”
$return|Where-Object -FilterScript{$.replacementstrings[8] -eq 2}|foreach-object{$.replacementstrings[5]}|Group-Object|Sort-Object -Property Count -Descending
- The rest of the script just repeats this logic for all of the different logon types. For the logon type 2 (which is a interactive logon of the console) get all of the events from the query of the event log for this logon type. Group them and sort by a count per user in a descending order. The Write-output just explains what the Logon type is being returned.
So while the script does not give you the last three logons it will quickly tell you the most active users and how they are logging on. There is the output from one of my windows 10 workstations

Logon Type 2 - interactive

Count Name                      Group                                                                                              
----- ----                      -----                                                                                              
    6 DWM-1                     {DWM-1, DWM-1, DWM-1, DWM-1...}                                                                    
Logon Type 3 - network
Logon Type 4 - batch
Logon Type 5 - service
  375 SYSTEM                    {SYSTEM, SYSTEM, SYSTEM, SYSTEM...}                                                                
    4 UpdatusUser               {UpdatusUser, UpdatusUser, UpdatusUser, UpdatusUser}                                               
    3 IUSR                      {IUSR, IUSR, IUSR}                                                                                 
    3 LOCAL SERVICE             {LOCAL SERVICE, LOCAL SERVICE, LOCAL SERVICE}                                                      
    3 NETWORK SERVICE           {NETWORK SERVICE, NETWORK SERVICE, NETWORK SERVICE}                                                
Logon Type 7 - unlock
    4 jon.warnken@gmail.com     {jon.warnken@gmail.com, jon.warnken@gmail.com, jon.warnken@gmail.com, jon.warnken@gmail.com}       
Logon Type 8 - networkceartext
Logon Type 9 - newcredentials (Runas)
Logon Type 10 - remoteinteractive
Logon Type 11 - cachedinteractive
    4 jon.warnken@gmail.com     {jon.warnken@gmail.com, jon.warnken@gmail.com, jon.warnken@gmail.com, jon.warnken@gmail.com}       

Hi Jonathan,
wow great. I tested in and it Works.

Could the computername variable? be edited so it uses a list of servers, saved in .txt ?

And output the server and 3 last logins on a line and then a new line for each server?

Thx sofar jonathan

Best regards

You should consider making this more of a PSObject so that you can perform queries against it. Try something like this

function Get-Logon {
    param (
        [string[]]$ComputerName = "."
    begin {
        #Put the logon types in a hash table to do lookups
        $logonType = @{
            2 =	 "Interactive"
            3 =  "Network"
            4 =	 "Batch"
            5 =  "Service"
            7 =	 "Unlock"
            8 =	 "NetworkCleartext"
            9 =	 "NewCredentials"
            10 = "RemoteInteractive"
            11 = "CachedInteractive"
    process {
        $results = foreach ($computer in $ComputerName) {
            Write-Verbose ("Processing computer {0}" -f $Computer)
            $params = @{
                ComputerName = $Computer
                LogName = "Security"
                InstanceID = 4624
                ErrorAction = "Stop"
            try {
                $return = Get-EventLog @params
                if ($return) {
                    Write-Verbose ("Found {0} records on {1}" -f $return.Count, $Computer)
                    $return | Select EntryType, 
                else {
                    Write-Verbose ("No records found on {0}" -f $Computer)
            catch {
                $msg = ("Unable to collect event information from {0}. {1}" -f $Computer, $_)
                Write-Verbose $msg
                $props = @{
                    EntryType = "Error"
                    TimeGenerated = $null
                    LogonType = $msg
                    User = $null
                    LogonTypeName = $null
                    ComputerName = $Computer

                New-Object -TypeName PSObject -Property $props
        } #foreach
    } #process
    } #end
} #Get-Logon

$logons = Get-Logon

Once you have the logon information, you can filter it as needed. You could get logon counts like this:

PS C:\WINDOWS\system32> $logons | Group-Object LogonTypeName -NoElement | Sort-Object Count -Descending

Count Name                     
----- ----                     
 2910 Service                  
  106 Unlock                   
  106 CachedInteractive        
   12 Interactive              
    6 Network         

As far returning the first 3, is that the top 3 interactive logons? You can add parameters to the function to return only what you care about. The function allows you do multiple computers:

$logons = Get-Logon -ComputerName "Computer1", "Computer2", "Computer3"
$logons = Get-Logon -Computername (Get-Content C:\Servers.txt)