Post

Event Handling in PowerShell with C# Managed Code

Event Handling in PowerShell with C# Managed Code

Introduction

Integrating C# code within PowerShell can extend its capabilities significantly. By embedding custom C# classes, PowerShell can handle more complex operations such as event handling with a higher degree of control.

In this post, I will walk you through a straightforward example of using pure C# code to instantiate a Timer object, expose its lapse event, and demonstrate how to subscribe to this event with a custom event handler in PowerShell.

The Embedded C# Code

Let’s start by embedding C# code in PowerShell.

This C# snippet defines a ProcessMonitor class that triggers an event every second, incrementing a counter each time:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
$code = @"
using System;
using System.Timers;

namespace PowerShellEventDemo
{
    public class ProcessEventArgs : EventArgs
    {
        public string ProcessInfo { get; set; } // Holds process info
        public int Counter { get; set; } // Counter value
    }

    public class ProcessMonitor
    {
        public event EventHandler<ProcessEventArgs> TimeChanged; // Event to notify when timer elapses
        private int _counter = 0;
        private static Timer timer; // Timer instance

        public void Start()
        {
            timer = new Timer { Interval = 1000, AutoReset = true, Enabled = true }; // Timer setup
            timer.Elapsed += Timer_Elapsed; // Attach event handler
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            _counter++; // Increment counter

            // Whenever the timer object emits an event it will raise our custom OnTimeChanged event that will be subscribed by our PowerShell code

            OnTimeChanged(new ProcessEventArgs // Raise event
            {
                ProcessInfo = String.Format("Counter: {0} Time: {1}", _counter, e.SignalTime),
                Counter = _counter
            });
        }

        protected virtual void OnTimeChanged(ProcessEventArgs e)
        {
            TimeChanged.Invoke(this, e); // Invoke event
        }

        public void Stop()
        {
            timer.Stop(); // Stop timer
        }
    }
}
"@

Add-Type -TypeDefinition $code  # Add the defined C# code to the current PowerShell session

Setting Up Event Handling in PowerShell

With the C# class added to our PowerShell session, we can create an instance of ProcessMonitor and register an event handler using Register-ObjectEvent:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# Creates an instance of the `ProcessMonitor` class defined in the embedded C# code
$monitor = New-Object PowerShellEventDemo.ProcessMonitor 

# Registers an event handler for the `TimeChanged` event, specifying the action to take when triggered
Register-ObjectEvent -InputObject $monitor -EventName TimeChanged -Action {
    
    # Extracts the event arguments passed to the handler
    $eventArgs = $Event.SourceEventArgs 
    
    Write-Host "PowerShell received: $($eventArgs.ProcessInfo)"

    # Checks if the counter has reached 10 and triggers the stop process 
    if ($eventArgs.Counter -eq 10) { 
        Write-Host "Counter: $($eventArgs.Counter) - Stop" -ForegroundColor Yellow
        $monitor.Stop() 

        # Unregisterr the event to prevent memory leak and remove the job
        Get-EventSubscriber | Unregister-Event
        Get-Job | Remove-Job
    }
}

# Start the timer
$monitor.Start() 

Running the code you should see the events being output to the console as the timer triggers each second:

PowerShell Output

Conclusion

Embedding C# code in PowerShell scripts lets you take advantage of event handling, making it possible for automation tasks to respond dynamically to specific conditions. This example shows how PowerShell’s flexibility can be combined with the power of C# to create more advanced scripting solutions.

I hope you enjoyed this post and learned something new about PowerShell!

References

  1. PowerShell and Events
  2. Executing C# code using PowerShell script
  3. Timer.Elapsed
This post is licensed under CC BY 4.0 by the author.