Every System Administrator comes into a situation where you want to see who and how many users were logged on to your servers either via Remote Desktop or via script.
This little function evaluates the System log with the help of Get-EventLog and delivers you the latest logon and logoff events for every user.
I’ve left you the Invoke-Command commented if you want to use PowerShell Remoting (WinRM).
FunctionGet-LogonHistory{<#
.SYNOPSIS Retrieves history of last logged on users with usernames and respective logoff/logon times.
.DESCRIPTION Retrieves history of last logged on users with usernames and respective logoff/logon times.
.PARAMETER Newest
This command gets the most recent entries from the event log according to its value.
.PARAMETER ComputerName
A single Computer or an array of computer names. The default is localhost ($env:COMPUTERNAME).
.PARAMETER Credentials
Commit Credentials for a different domain.
.PARAMETER Verbose
Run in Verbose Mode.
.EXAMPLE PS C:\> Get-LogonHistory -ComputerName SERVER1 -Credentials Get-Credential -Newst
.NOTES Author: Sebastian Gräf
Email: ps@graef.io
Date: April 15, 2017
PSVer: 2.0/3.0/4.0/5.0
#>[Cmdletbinding()]Param([Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)][string[]]$ComputerName=$Env:COMPUTERNAME,[Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)][string]$Newest=10,[Parameter(ValueFromPipelineByPropertyName=$true,ValueFromPipeline=$true)][ValidateNotNull()][System.Management.Automation.PSCredential][System.Management.Automation.Credential()]$Credentials=[System.Management.Automation.PSCredential]::Empty)Begin{Write-Verbose" [$($MyInvocation.InvocationName)] :: Start Process"$Results=@()$ProgressCounter=0}Process{foreach($Computerin$ComputerName){$ProgressCounter++Write-Progress-activity"Running on $Computer"-status"Please wait ..."-PercentComplete(($ProgressCounter/$ComputerName.length)*100)if(Test-Connection$Computer-Count1-Quiet){Write-Verbose" [$($MyInvocation.InvocationName)] :: Processing $Computer"try{$ELogs=Get-EventLogSystem-SourceMicrosoft-Windows-WinLogon-ComputerName$Computer-Newest$Newest#$ELogs = Invoke-Command { param ($Newest) Get-EventLog System -Source Microsoft-Windows-WinLogon -Newest $Newest } -ArgumentList $Newest -ComputerName $ComputerForEach($Login$ELogs){If($Log.InstanceId-eq7001){$EventType="Logon"}ElseIf($Log.InstanceId-eq7002){$EventType="Logoff"}Else{Continue}$Results+=New-ObjectPSObject-Property@{User=(New-ObjectSystem.Security.Principal.SecurityIdentifier$Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])Time=$Log.TimeWritten'Event Type'=$EventType}}$Results}catch{Write-Verbose" Host [$Computer] Failed with Error: $($Error[0])"}}else{Write-Verbose" Host [$Computer] Failed Connectivity Test"}}$result|Select User,Time,"Event Type"|Sort Time-Descending}End{Write-Progress-activity"Running on $Computer"-Status"Completed."-CompletedWrite-Verbose" [$($MyInvocation.InvocationName)] :: End Process"}}
Please keep in mind, it evaluates every event, this means even if a user was doing actions remotely using a powershell script or just logged on, it will be displayed as well. If you want to distinguish between script logons you can easily have a look at the logon and logoff times. If a user account was only logged for some seconds … then this is an indicator for a remote script logon.
The script will give you following output:
While using following command you can also query this function to more than just one server: