Hi,
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. 
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
4 ANONYMOUS LOGON {ANONYMOUS LOGON, ANONYMOUS LOGON, ANONYMOUS LOGON, ANONYMOUS LOGON}
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 {
[CmdLetBinding()]
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"
}
}#begin
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,
TimeGenerated,
@{Name="LogonType";Expression={$_.replacementstrings[8]}},
@{Name="User";Expression={$_.replacementstrings[5]}},
@{Name="LogonTypeName";Expression={$logonType.Get_Item([int]$_.replacementstrings[8])}},
@{Name="ComputerName";Expression={$Computer}}
}
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{
$results
} #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
7
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"
#or
$logons = Get-Logon -Computername (Get-Content C:\Servers.txt)