4 min read
How to Leverage IT Automation for Maximum Efficiency
Are you ready for a transformation of your IT operations? Our brand-new white paper, Maximizing IT Automation: The...
ScriptRunner Blog
The Oxford dictionary defines an event as “a thing that happens, especially something important”. In the computing world most people associate events with logging, however events go beyond that. In fact, a log is nothing but an output from an event.
This blog post covers two types of events, PowerShell Engine Events and .NET Object Events (click here for part 2 of the series, Handling events with PowerShell and WMI).
Keep on reading if you want to learn how to handle both PowerShell Engine Events and .NET Object Events and which PowerShell commandlets will get you there.
Simple, right? Let’s simplify this using a real-world example.
I’m an object of my parents class. My parents have certain properties such as black hair, brown eyes etc. and certain methods such as cooking, dancing etc.
Let’s take a simple example of a class defined in PowerShell:
class PrintName {#Define a class [Int] $count #Property [Void] WriteHello([string] $Name){ #Function Write-Host "Hello $Name" } } $Obj = [PrintName]::new() #Instantiate an Object $Obj.count = 1 #Assign value for count property Write-Host "Property Value " $obj.count $Obj.WriteHello('Sonny') #Call GetProcessPath method "`n"
Which delivers the following output:
Property Value 1 Hello Sonny
In the example above we created a class called “PrintName” with one property called “count” and method called “WriteHello”. But why are we talking about classes?
Well, to understand events we need to first understand class structure because an event is nothing but a special kind of method.
Special, because other pieces of code can subscribe to events (this is also known as event subscription).
In order to enable other programs to be informed about certain actions or state changes by a specific program, we need to create events in that program.
Thus, other programs can subscribe to these events and get informed when certain actions or state changes happen in your program (don’t worry, when we discuss .NET Framework events things would become clearer).
PowerShell provides different cmdlets for working with events. Let’s start with the New-Event cmdlet (Figure 1), which, as the name suggests, creates a new Event.
New-Event
[-SourceIdentifier]
[[-Sender] ]
[[-EventArguments] <psobject[]>]
[[-MessageData] ]
[]</psobject[]>
Remove-Event [-SourceIdentifier] [-WhatIf] [-Confirm] []
Remove-Event [-EventIdentifier] [-WhatIf] [-Confirm] []
Figure 3: The Remove-Event cmdlet deletes events from the event queue in the current session.
As we can see, we only have one event left in the event queue.
Before we move on, let’s clear the event queue by running the following cmdlet
Remove-Event -SourceIdentifier *
At this point there are no events in our event queue.
In order to view current subscriptions in a session, use the Get-EventSubscriber cmdlet. Both Register-EngineEvent and Get-EventSubscriber cmdlet are shown in Figure 4.
Register-EngineEvent [-SourceIdentifier] [[-Action] ] [-MessageData ] [-SupportEvent] [-Forward] [-MaxTriggerCount ] []
Get-EventSubscriber
[[-SourceIdentifier] ]
[-Force]
[]
Get-EventSubscriber [-SubscriptionId] [-Force] []
As we can see in Figure 5, when we raise the event named “MyEvent”, the event subscriber is invoked and executes the Action Script Block.
Unregister-Event [-SourceIdentifier] [-Force] [-WhatIf] [-Confirm] []
Unregister-Event
[-SubscriptionId]
[-Force]
[-WhatIf]
[-Confirm]
[]
Let’s start by taking a simple example of the Process class which is part of the System.Diagnostic namespace.
As we can see in Figure 7 the Process class has constructor, properties, methods and events. Collectively they are also known as class members. The Process class also has three events:
In order to access class members, we need to either instantiate a new Object or use existing objects. Once we have an object, we can use it to subscribe to the events.
PowerShell provides the Register-ObjectEvent cmdlet to subscribe to .NET framework events.
Let’s take an example, suppose that we want to subscribe to the “exiting” event of Process class. In order to do so, we first need an Object of Process class. We can then use the object to subscribe to the Member events of the Process class.
The exiting event is invoked when a process exits. In our example we will use the calculator process object to subscribe to the exiting event.
Any process running on Windows is an Object. To get a list of process objects on windows we can use the Get-CimInstance cmdlet. As you can see in Figure 8 the Get-CimInstance returns the objects and by combining it with the Get-Member cmdlet we can view the class members.
Get-CimInstance [-ClassName] [-ComputerName <string[]>] [-KeyOnly] [-Namespace ] [-OperationTimeoutSec ] [-QueryDialect ] [-Shallow] [-Filter ] [-Property <string[]>] []</string[]></string[]>
For our example we launch the calculator process in our code. We always have the option to use an already existing process object. In the code below we are first starting the calculator process and capturing the object in $CalcProcessObj variable.
$CalcProcessObj = [System.Diagnostics.Process]::Start("calc.exe") Register-ObjectEvent -InputObject $CalcProcessObj -EventName Exited -Action { cmd.exe /c ping -n 2 8.8.8.8 }
Next, we use the Register-ObjectEvent cmdlet to subscribe to the exited event for the calculator process.
Register-ObjectEvent [-InputObject] [-EventName] [[-SourceIdentifier] ] [[-Action] ] [-MessageData ] [-SupportEvent] [-Forward] [-MaxTriggerCount ] []
When the calculator process exits our action block will be executed. The Action block contain a simple command to send 2 pings to IP address 8.8.8.8. Figure 9 shows the output that we have successfully subscribed to the event.
Once we exit the calculator process, we can see that the Action Script block was executed and resulted in 2 pings being sent to IP address 8.8.8.8 (Figure 10).
As we have seen before we can use the Get-EventSubscriber cmdlet for getting a list of all event subscriptions.
The output in our example is shown in Figure 11.
Similarly, we can use the Unregister-Event cmdlet to unregister an event subscription (don’t you love the verb-noun representation of cmdlets 😊), as can be seen in Figure 12 .
Suppose we want to subscribe to file/directory creation event.
We follow the same steps from our last example:
Let’s first create an Object of FileSystemWatcher class
$testobj1 = New-Object -TypeName System.IO.FileSystemWatcher
Next, we give our object the directory path to watch for file/directory creation
$testobj1.Path = "C:\Users\Public"
Register-ObjectEvent -InputObject $testobj1 -EventName Created -Action { cmd.exe /c ping -n 2 8.8.8.8 }
We follow the same steps as before: we instantiate an object, set the Log property for the object (= which log we want to watch) and then use the Register-ObjectEvent cmdlet to subscribe to the EntryWritten event.
$testobj1 = New-Object -TypeName System.Diagnostics.EventLog $testobj1.Log = "Security" Register-ObjectEvent -InputObject $testobj1 -EventName EntryWritten -Action { Write-Host "Meow" }
Please note: this code requires admin level permission as we are working with logging.
Figure 14: EntryWritten event for EventLog class
For this demonstration I switched from VS Code to ISE. Figure 15 shows how we subscribed to the EntryWritten event for Security logs. Our action blocks write “Meow” each time the event is invoked.
Figure 15: Subscribing for “EntryWritten” event
In the next part we will be discussing, how to handle WMI eventing with PowerShell.
You can leverage your monitoring capabilities even more by using ScriptRunners Report/Audit DB Connector. It lets you store all your reports on script execution in one central repository and provides you with complete traceability of all processes.
Nov 28, 2024 by Heiko Brenn
Are you ready for a transformation of your IT operations? Our brand-new white paper, Maximizing IT Automation: The...
Nov 21, 2024 by Guy Leech
Perhaps it is because I began my professional coding career writing device drivers for Unix systems in C, back in the...
Nov 20, 2024 by Damian Scoles
What is Microsoft Purview for you? Do you already master data governance with it? Learn how PowerShell simplifies...
Sonny is a self-proclaimed PowerShell preacher who lives in the beautiful city of Halifax on the east coast of Canada. Sonny has worked in Cybersecurity for more than 10 years and has acted as the primary technical lead and subject matter expert on many Cyber Security Assessments for various private and public organizations. Sonny regularly speaks at various security conferences such as BSides, AtlSecCon, ISACA, OWASP etc.