Posted On October 7, 2020

PowerShell: Get Event Logs from a List of Computers

kimconnect 0 comments
blog.KimConnect.com >> Codes >> PowerShell: Get Event Logs from a List of Computers

Windows event logs contain a wealth of information that would be useful for analytical purposes. Here’s a function to quickly gather all events matching certain ID.

#getEventLogs.ps1
#Version: 0.0.1

$computerNames=get-content C:\computers.txt
$logType='Security'
$eventId=4625
$adminCredentials=$false # leave this as False to generate during runtime

function getEventLogs{
    param(
        $computerNames,
        $logType,
        $eventId,
        $adminCredentials
    )
    if(!$adminCredentials){
        $adminCredentials=obtainDomainAdminCredentials
    }
    function getLogs{
        param(
            $computerNames,
            $logType,
            $eventId,
            $adminCredentials
        )
        get-job|stop-job|remove-job        
        foreach ($computerName in $computerNames){
            $getEventLog={
                    param($computerName,$logType,$eventId,$adminCredentials)
                    $session=.{
                        try{
                            if($adminCredentials){
                                New-PSSession -ComputerName $computerName -Credential $adminCredentials -EA Stop
                            }else{
                                New-PSSession -ComputerName $computerName -EA Stop
                            }
                        }catch{
                            if($adminCredentials){
                                New-PSSession -ComputerName $computerName -Credential $adminCredentials -SessionOption $(new-pssessionoption -IncludePortInSPN)
                            }else{
                                New-PSSession -ComputerName $computerName -SessionOption $(new-pssessionoption -IncludePortInSPN)
                            }
                        }
                    }
                    $logs=invoke-command -session $session -scriptblock{
                        param($logType,$eventId)
                        Get-EventLog $logType|?{$_.eventid -eq $eventId}
                    } -Args $logType,$eventId
                    if($session){Remove-PSSession $session}
                    return $logs|Select-Object -Property * -ExcludeProperty PSComputerName,RunspaceId
                }
            start-job -Name $computerName -ScriptBlock $getEventLog -Args $computerName,$logType,$eventId,$adminCredentials
        }

        $lineBreak=60
        $dotCount=0
        $minute=0
        write-host "Minute`r`n$minute`:" -NoNewline -ForegroundColor Yellow
        [System.Collections.ArrayList]$jobResults=@() # ArrayList from .NET is mutable, hence useful for adding elements
        [int16]$jobsCount=(get-job).count
        do{        
            $completedJobs=get-job|?{$_.State -eq 'Completed'}
            foreach ($job in $completedJobs){
                $computer=$job.Name
                write-host "`r`n===================================================`r`n$computer job completed:`r`n===================================================`r`n"
                $jobResult=[pscustomobject]@{
                    computerName=$computer                
                    timeStamp=$job.PSEndTime
                    minutesElapsed=[math]::round(($job.PSEndTime-$job.PSBeginTime).TotalMinutes,2)
                    result=receive-job -id $job.id
                }                
                $jobResults.Add($jobResult)
                remove-job -Id $job.id
            }
            if($dotCount++ -lt $lineBreak){
                write-host '.' -NoNewline
            }else{
                $minute++
                write-host "`r`n$minute`t:" -ForegroundColor Yellow -NoNewline
                $dotCount=0
                }
            Start-Sleep -seconds 1
        }until($jobsCount -eq $jobResults.count -or !(get-job))
        write-host "`r`n$(($jobResults|ft|out-string).trim())"
        return $jobResults
    }

    $eventLogs=(getLogs $computerNames $logType $eventId $adminCredentials).Result
    return $eventLogs
}

$eventLogs=getEventLogs $computerNames $logType $eventId $adminCredentials
$eventLogs|Group-Object -Property MachineName
# Example of generating information from Event Logs

$computerNames='crm01','crm02','crm03','crm04'
$logType='Application'
$eventId=17972
$adminCredentials=$false # leave this as False to generate during runtime
# ..... #
$eventLogs=getEventLogs $computerNames $logType $eventId $adminCredentials

# Shows the count of logs on each computer
$eventLogs|Group-Object -Property MachineName

# Get statistical information
[System.Collections.ArrayList]$timeArray=@()
foreach ($log in $eventLogs){
    $seconds=[regex]::match($log.Message,'([\d\.]+)\sseconds').captures.groups[1].value
    $timeArray+=$seconds
}
$max=($timeArray|Measure-Object -Max).Maximum
$frequencyOfMax=($timeArray|?{[int]$_ -ge $max}).count
$min=($timeArray|Measure-Object -Min).Minimum
$frequencyOfMin=($timeArray|?{[int]$_ -le $min}).count
$average=[math]::round(($timeArray|Measure-Object -Average).Average,2)
write-host "Max: $max (x$frequencyOfMax)`r`nMin: $min (x$frequencyOfMin)`r`nAverage: $average"

Leave a Reply

Your email address will not be published. Required fields are marked *

Related Post

PowerShell: Detect Windows Version

This little snippet is reusable on many occasions where Windows version targeting is required. function…

Microsoft SQL AlwaysOn High Availability Cluster Management Tool

There are some bugs in the script. I'm too lazy to go back a fix…

PowerShell: How To Disable and/or Stop Windows Service

Disable and Stop Using Native Command 'Set-Service' # To disable service as well as stopping…