First my apologies for the wall of text. You should look into the New-Event, Register-EngineEvent, Unregister-Event, Get-Event, Get-EventSubscriber, and Remove-Event cmdlets. Here is a quick sample on working with these events to fire off and handle your own events.
First we will setup 2 small functions. This writes some automatic variables to the console:
function Write-EventToConsole ($evt)
{
Write-Host "Write info to the console from a function"
Write-Host $Evt.MessageData
Write-Host $Evt.Sender
Write-Host $Evt.TimeGenerated
Write-Host $Evt.SourceArgs
}
This one just appends them to a file:
function Save-EventToFile ($evt, $filepath)
{
"Writing to file" | Out-File $filepath -Append
"Message Data : {0}" -f $Evt.MessageData | Out-File $filepath -Append
"Sender : {0}" -f $Evt.Sender | Out-File $filepath -Append
"Time Generated : {0}" -f $Evt.TimeGenerated | Out-File $filepath -Append
"Source Args : {0}" -f $Evt.SourceArgs | Out-File $filepath -Append
}
Next we will setup 3 event handlers. We will do these 1 at a time, check the subscribers, and fire an event after each one.
Register-EngineEvent -SourceIdentifier "MyEventIdentifier" -Action {
Write-EventToConsole $Event
} -SupportEvent
Next check to see if our event subscriber is there.
Get-EventSubscriber -Force
SubscriptionId : 1
SourceObject :
EventName :
SourceIdentifier : MyEventIdentifier
Action : System.Management.Automation.PSEventJob
HandlerDelegate :
SupportEvent : True
ForwardEvent : False
Then we fire the event
$null = New-Event -SourceIdentifier "MyEventIdentifier" `
-Sender "MyObject" `
-EventArguments "Some arguments that I want to pass" `
-MessageData "This is some message data I want to pass"
And see the data written to console.
just write to console
This is some message data I want to pass
MyObject
MyObject
4/5/2019 1:54:27 PM
Some arguments that I want to pass
Some arguments that I want to pass
Adding the additional events:
Register-EngineEvent -SourceIdentifier "MyEventIdentifier" -Action {
Write-EventToConsole $Event
} -SupportEvent
Register-EngineEvent -SourceIdentifier "MyEventIdentifier" -Action {
Save-EventToFile $Event C:\temp\event.txt
} -SupportEvent
Check the events subscribers:
Get-EventSubscriber -Force
SubscriptionId : 1
SourceObject :
EventName :
SourceIdentifier : MyEventIdentifier
Action : System.Management.Automation.PSEventJob
HandlerDelegate :
SupportEvent : True
ForwardEvent : False
SubscriptionId : 2
SourceObject :
EventName :
SourceIdentifier : MyEventIdentifier
Action : System.Management.Automation.PSEventJob
HandlerDelegate :
SupportEvent : True
ForwardEvent : False
SubscriptionId : 3
SourceObject :
EventName :
SourceIdentifier : MyEventIdentifier
Action : System.Management.Automation.PSEventJob
HandlerDelegate :
SupportEvent : True
ForwardEvent : False
Now if we fire an event:
$null = New-Event -SourceIdentifier "MyEventIdentifier" `
-Sender "MyObject" `
-EventArguments "Some arguments that I want to pass" `
-MessageData "This is some message data I want to pass"
We can see that the 2 event subscribers that write to console fired:
just write to console
This is some message data I want to pass
MyObject
MyObject
4/5/2019 1:54:27 PM
Some arguments that I want to pass
Some arguments that I want to pass
Write info to the console from a function
This is some message data I want to pass
MyObject
4/5/2019 1:54:27 PM
Some arguments that I want to pass
And the event subscriber that wrote to file fired:
Get-Content C:\temp\event.txt
Writing to file
Message Data : This is some message data I want to pass
Sender : MyObject
Time Generated : 4/5/2019 1:54:27 PM
Source Args : Some arguments that I want to pass
Finally to remove the event subscribers you can use:
Get-EventSubscriber -Force | `
Where-Object { $_.SourceIdentifier -eq 'MyEventIdentifier' } | `
Unregister-Event -Force
Hopefully this helps explain this a bit. If not, let me know and I will update the answer to address any questions.
Edit:
This also works with classes. Here is a quick sample. Note that if you return a value it may not be usable if you use -SupportEvent. Removing SupportEvent will run the action as a PSEventJob. This will let you use Get-Job and Receive-Job to retrieve the value.
# Define a class
class TestSubscribeEvent
{
# Static method
static [void] DisplayMessage($evt)
{
Write-Host "Written from static handler"
Write-Host $Evt.MessageData
Write-Host $Evt.Sender
Write-Host $Evt.TimeGenerated
Write-Host $Evt.SourceArgs
Write-Host '----------------------------'
}
[string] DisplayMessage2($evt)
{
return "You wont see this if you use supportevent"
}
[void] SetSomeProperty($evt)
{
$this.SomeProperty ="Set from internal instance`n`t{0}`n`t{1}`n`t{2}`n`t{3}" -f $Evt.MessageData, $Evt.Sender, $Evt.TimeGenerated, $Evt.SourceArgs
}
[string] $SomeProperty
}
# Define a class
class TestEvent
{
# Static method
static [void] SendMessage($msg)
{
$null = New-Event -SourceIdentifier "MyEventIdentifier" `
-Sender "MyObject" `
-EventArguments "Sent from static" `
-MessageData $msg
}
[void] SendMessage2($msg)
{
$null = New-Event -SourceIdentifier "MyEventIdentifier" `
-Sender "MyObject" `
-EventArguments "Sent from instance" `
-MessageData $msg
}
}
Make some objects:
$subObj = New-Object TestSubscribeEvent
$testEvent = New-Object TestEvent
Register some event handlers
#register static handler
Register-EngineEvent -SourceIdentifier "MyEventIdentifier" -Action {
[TestSubscribeEvent]::DisplayMessage($event)
} -SupportEvent
#register instance handler
Register-EngineEvent -SourceIdentifier "MyEventIdentifier" -Action {
$subObj.DisplayMessage2($event)
} -SupportEvent
#register instance handler without Support Event
#this creates a PSEventJob which we swallow with $null, we check it later
$null = Register-EngineEvent -SourceIdentifier "MyEventIdentifier" -Action {
$subObj.DisplayMessage2($event)
}
#register instance handler that updates a property
Register-EngineEvent -SourceIdentifier "MyEventIdentifier" -Action {
$subObj.SetSomeProperty($event)
} -SupportEvent
Now we will call the event generators:
#call static generator
[TestEvent]::SendMessage("Static called message")
This generates the following to the console:
Written from static handler
Static called message
MyObject
4/9/2019 8:51:20 AM
Sent from static
----------------------------
We can see that it was a static method that was called, that the new event was created in the static method, and that the static handler got it.
We can also use get-job to see the PSEventJob running.
Id Name PSJobTypeName State HasMoreData Location Command
-- ---- ------------- ----- ----------- -------- -------
47 MyEventIdent... Running True ...
You can then use Get-Job 47 | Receive-Job -keep
to get the output
You wont see this if you use supportevent
Note that the other handler that called the same method that returned a value and did use SupportEvent basically lost all output. No PSEventJob was created so the output had nowhere to go.
We can also see the property was set on the instance object.
$subObj.SomeProperty
Set from internal instance
Static called message
MyObject
4/9/2019 9:05:26 AM
System.Object[]
The instance version does essentially the same thing all over just passing the different values.
#call instance generator
$testEvent.SendMessage2("Instance called message")
This give the following:
Written from static handler
Instance called message
MyObject
4/9/2019 9:02:02 AM
Sent from instance
----------------------------