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 *