Hunting Event Logs

Hunt-EventLog function monitors a specific Event log like Application, System or any other and triggers an action when a specific Event occurs. By default it looks for changes in the Event log every 30 seconds and searches the EventID; you can change this interval with -Interval paramaters. Hunt-EventLog echoes information in every interval which can be silenced with -Silent $true

Hunt-EventLog also can be called as a background job with -AsJob $true parameter. When you call Hunt-EventLog with -AsJob $true parameter it returns the Job object that is created for it; so you can assign it to a variable to return the output later. AsJob parameter works only if you copy the Hunt-EventLog.ps1 file under C:\ps\library\Hunt-EventLog.ps1. I will post another blog about how I'm using these scripts in my own environment

Hunt-EventLog

Here is the function code; as usual check the attachment to get it in ps1 format 

function Hunt-EventLog
{

<#

.Synopsis
 Searches for a specific EventID in Event Viewer and gives a specific response
.Description
 This cmdlet loops until it finds the EventID that user enters and gives the response user wants
.Parameter EventID
 Specifies EventID that is being search for
.Parameter LogName
 Specifies the name of the event log. EventID will be searched in this log
.Parameter ScriptString
    Specifies the action commands to run. Enclose the commands in double quotes ( " " ) to create a script string
.Parameter Interval
 Specifies the wait interval between the executions of the function. The value of this parameter is second and default value is 30 seconds
.Parameter Silent
 Specifies whether output to the screen is allowed or not
.Parameter AsJob
 Creates a background job for the cmdlet and echoes the jobID
.Example
Hunt-EventLog -LogName Application -EventID 8225 -ScriptString "do something"
.Example
Hunt-EventLog -LogName Application -EventID 8225 -Interval 60
.Link
 https://blogs.msdn.com/candede
.Notes
 Author: Can Dedeoglu
#>

param
(
[Parameter(mandatory=$true,position=0)]
[string]$LogName
,
[Parameter(mandatory=$true,position=1)]
[string]$EventID
,
[Parameter(mandatory=$true)]
[string]$ScriptString
,
[Parameter(mandatory=$false)]
[int]$Interval = 30
,
[Parameter(mandatory=$false)]
[bool]$Silent = $false
,
[Parameter(mandatory=$false)]
[bool]$AsJob = $false
)

$startupLog = Get-EventLog $LogName -Newest 1
$startupTime = $startupLog.TimeGenerated
$startupIndex = $startupLog.Index

[bool]$logsCaptured = $false

function startControl([datetime]$time)
{

function writeConsole([int]$output)
{
if(!$Silent)
{
 switch($output)
 {
 1
  {
  $(Get-Date).tostring("HHmmss") + ": Logs between Index " + ($newLogs[-1]).Index  + "-" + ($newLogs[0]).Index + " has been scanned; there is no match"
  }
 2
  {
  (Get-Date).tostring("HHmmss") + ": sleeping " + $Interval + " seconds"
  }
 3
  {
  (Get-Date).tostring("HHmmss") + ": no new logs, last log Index was " + $currentIndex
  }
 }
}
}

$newLogs = @(Get-EventLog $LogName -After $time)

if(!$logsCaptured)
    {
    $currentIndex = $startupIndex
    $currentTime = $startupTime
    }

if($newLogs.count -gt 0)
    {
    $newTime = ($newLogs[-1]).TimeGenerated
    $results = @($newLogs | ?{$_.InstanceId -eq $EventID})
   
    if($results.count -gt 0)
        {
        Invoke-Command -ScriptBlock ([scriptblock]::Create($ScriptString))
        }
    else
        {
        writeConsole(1)
        writeConsole(2)
        $currentIndex = ($newLogs[0]).Index
        $currentTime = ($newLogs[0]).TimeGenerated
        $logsCaptured = $true
        Start-Sleep -Seconds $Interval
        startControl $newTime
        }

    }
else
    {
    writeConsole(3)
    writeConsole(2)
    Start-Sleep -Seconds $Interval
    startControl $currentTime
    }
}

if(!$AsJob)
 {
 startControl $startupTime
 }

else
 {
 Start-Job -ScriptBlock ([scriptblock]::Create(". c:\ps\library\Hunt-EventLog.ps1; Hunt-EventLog -LogName $LogName -EventID $EventID -ScriptString `"$ScriptString`" -Interval $Interval -Silent `$$Silent"))
 }

}

 

Cheers, CanD

Hunt-EventLog.ps1