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"
Categories: