Skip to the main content.

ScriptRunner Blog

Nutze .NET in PowerShell für ereignisgesteuertes Scripting

Inhaltsverzeichnis

Post Featured Image

Erweitere PowerShell mit .NET für eine leistungsstarke Ereignisautomatisierung. Systemereignisse wie ein Profi überwachen und verarbeiten! Der Artikel beantwortet die Frage, wie du .NET-Klassen nutzen kannst, um Ereignisse zu überwachen und automatisierte Antworten auszulösen und so die Möglichkeiten der PowerShell für eine effiziente Systemverwaltung zu erweitern.

Das Oxford-Wörterbuch definiert ein Ereignis als "eine Sache, die passiert, besonders etwas Wichtiges". In der Computerwelt assoziieren die meisten Menschen Ereignisse mit der Protokollierung, aber Ereignisse gehen darüber hinaus. Tatsächlich ist ein Protokoll nichts anderes als eine Ausgabe eines Ereignisses.

Dieser Blogbeitrag behandelt zwei Arten von Ereignissen, PowerShell Engine Events und .NET Object Events (klickehier für den zweiten Teil, Meistere PowerShell WMI: überwache automatisiert System-Events). 

Wir schauen uns an, wie wir sowohl mit PowerShell-Engine-Ereignissen als auch mit .NET-Objekt-Ereignissen umgehen können und welche PowerShell-Befehle dabei helfen.

 

Die Grundlagen: Von PowerShell-Klassen und -Objekten bis zu Ereignissen

Bevor wir uns in die Details von PowerShell-Ereignissen vertiefen, müssen wir zunächst Klassen und Objekte verstehen.

  • Eine Klasse ist eine Sammlung von Eigenschaften und Methoden.
  • Ein Objekt ist eine Instanz der Klasse, die für den Zugriff auf Eigenschaften und Methoden verwendet wird.

Einfach, oder? Vereinfachen wir dies anhand eines realen Beispiels.

Ich bin ein Objekt der Klasse meiner Eltern. Meine Eltern haben bestimmte Eigenschaften wie schwarze Haare, braune Augen usw. und bestimmte Methoden wie Kochen, Tanzen usw.

Ein einfaches Beispiel für eine in PowerShell definierte Klasse:

 
#Definiere eine Klasse
class PrintName {
    #Property
[Int] $count

#Funktion
[Void] WriteHello([String] $Name){ Write-Host "Hello $Name" } }

#Instantiiere ein Objekts
$Obj = [PrintName]::new()


#Wert für die Eigenschaft count zuweisen
$Obj.count = 1 Write-Host "Property Value" $Obj.count


#Aufruf der Methode GetProcessPath
$Obj.WriteHello('Sonny') "`n"

 

Das liefert folgende Ausgabe:


Property Value 1
Hallo Sonny

Im obigen Beispiel haben wir eine Klasse namens "PrintName" mit einer Eigenschaft namens "count" und einer Methode namens "WriteHello" erstellt. Aber warum reden wir über Klassen?

Nun, um Ereignisse zu verstehen, müssen wir zuerst die Klassenstruktur verstehen, denn ein Ereignis ist nichts anderes als eine spezielle Art von Methode.

Speziell, weil andere Teile des Codes Ereignisse abonnieren können (dies ist auch als Ereignisabonnement/event subscription bekannt).

 

PowerShell-Engine-Events

Um andere Programme über bestimmte Aktionen oder Zustandsänderungen eines bestimmten Programms zu informieren, müssen wir Ereignisse in diesem Programm erstellen.

Auf diese Weise können andere Programme diese Ereignisse abonnieren und werden informiert, wenn bestimmte Aktionen oder Zustandsänderungen in Ihrem Programm stattfinden (keine Sorge, wenn wir über .NET Framework-Ereignisse sprechen, werden die Dinge klarer).

PowerShell bietet verschiedene Cmdlets für die Arbeit mit Ereignissen. Beginnen wir mit dem Cmdlet New-Event, das, wie der Name schon sagt, ein neues Ereignis erstellt.

 

Erstellen eines Ereignisses: New-Event cmdlet

PowerShell bietet verschiedene Cmdlets für die Arbeit mit Ereignissen. Beginnen wir mit dem New-Event cmdlet, das, wie der Name schon sagt, ein neues Ereignis erzeugt.


New-Event
[-SourceIdentifier]
[[-Sender]]    
[[-EventArguments]<psobject[]>]    
[[-MessageData]]    
[     

Quelle: Microsoft

 

Das New-Event cmdlet erstellt ein neues PowerShell-Ereignis

 

Anzeigen der Ereigniswarteschlange: Get-Event cmdlet

Wenn ein Ereignis erstellt ist, wird es zum Ereignis-Warteschlange hinzugefügt. Um die Ereignis-Warteschlange anzuzeigen, verwenden wir die Get-Event cmdlet. Wir können unten sehen, dass es zwei Ereignisse in der Warteschlange gibt.


Get-Event
[[-SourceIdentifier]]
[]

Get-Event
[-EventIdentifier]
[]

Quelle: Microsoft

 

Die Ausgabe des Cmdlets Get-Event zeigt, dass sich derzeit zwei Ereignisse in der Ereigniswarteschlange befinden

Die Get-Event Cmdlet ruft Ereignisse in der PowerShell-Ereigniswarteschlange für die aktuelle Sitzung ab

 

Ereignisse aus der Warteschlange entfernen: Remove-Event cmdlet

Wie entfernen wir nun Ereignisse aus der Warteschlange? Wir verwenden die Remove-Event cmdlet wie unten gezeigt:


Remove-Event
[-SourceIdentifier]
[-WhatIf]
[-Confirm]
[]

 


Remove-Event
[-EventIdentifier]
[-WhatIf]
[-Confirm]
[]

Quelle: Microsoft

 

Das Cmdlet Remove-Event löscht Ereignisse aus der Ereigniswarteschlange

Das Remove-Event Cmdlet löscht Ereignisse aus der Ereigniswarteschlange der aktuellen Sitzung

 

Wie wir sehen können, haben wir nur noch ein Ereignis in der Ereigniswarteschlange.

Bevor wir weitermachen, leeren wir die Ereigniswarteschlange, indem wir das folgende Cmdlet ausführen


Remove-Event -SourceIdentifier *

Zu diesem Zeitpunkt befinden sich keine Ereignisse in unserer Ereigniswarteschlange.

 

Event-Anmeldung: Register-EngineEvent und Get-EventSubscriber cmdlet

Ereignisse sind nur dann nützlich, wenn jemand sie abonniert hat. Um ein Ereignis zu abonnieren, verwenden wir die Register-EngineEvent cmdlet wie unten gezeigt. Genau wie die Ereignisse, Ereignisabonnement zu der Sitzung hinzugefügt wird.

Um die aktuellen Abonnements in einer Sitzung anzuzeigen, verwenden wir das Cmdlet Get-EventSubscriber. Sowohl Register-EngineEvent als auch das Cmdlet Get-EventSubscriber werden hier gezeigt.


Register-EngineEvent
[-SourceIdentifier]
[[-Action]]
[-MessageData ]
[-SupportEvent]
[-Forward]
[-MaxTriggerCount]
[]

Quelle: Microsoft

 


Get-EventSubscriber
[[-SourceIdentifier]]
[-Force]
[]

 


Get-EventSubscriber
[-SubscriptionId]
[-Force]
[]

Quelle: Microsoft

 

Subscribing to 'MyEvent' by using the Register-EngineEvent cmdlet

Mit Hilfe des Cmdlets Register-EngingeEvent abonnieren wir das Ereignis "MyEvent"

 

Auslösen von Ereignissen in PowerShell

Im obigen Beispiel erstellen wir ein neues Abonnement für ein Ereignis namens "MyEvent". Wir lösen nun das Ereignis mit dem Namen "MeinEreignis" aus.

Wie wir jetzt sehen können, wird, wenn wir das Ereignis "MyEvent" auslösen, der Ereignisabonnent aufgerufen und führt den Aktions-Skriptblock aus.

Der Action-Block wird ausgeführt, wenn ein neues Ereignis mit dem Namen "MeinEreignis" aufgerufen wird

Der Aktionsblock wird ausgeführt, wenn ein neues Ereignis namens "MyEvent" aufgerufen wird 

 

Event-Abmeldung: Unregister-Event cmdlet

Um das Abonnement aus der aktuellen Sitzung zu entfernen, verwenden wir das Unregister-Event cmdlet:


Unregister-Event
[-SourceIdentifier]
[-Force]
[-WhatIf]
[-Confirm]
[]

 


Unregister-Event
[-SubscriptionId]
[-Force]
[-WhatIf]
[-Confirm]
[]

Quelle: Microsoft

 

Abbrechen eines Ereignisabonnements mit dem Cmdlet Unregister-Event in PowerShell

Aufheben der Registrierung des Ereignisabonnenten

 

.NET Framework-Events

Bislang haben wir PowerShell-Engine-Ereignisse besprochen. Wechseln wir nun den Fokus auf .NET Framework-Ereignisse. Eine vollständige Referenz für .NET finden sich unter .NET API browser.

Beginnen wir mit einem einfachen Beispiel der Klasse Process, die Teil des System.Diagnostic-Namensraumes ist.

Wie wir sehen, hat die Klasse Process einen Constructor, Properties, Methods und Events. Zusammen werden sie auch als Klassenmitglieder bezeichnet. Die Klasse Process hat auch drei Ereignisse:

  • ErrorDataReceived
  • Exited und
  • OutputDataReceived

Um auf Klassenmitglieder zugreifen zu können, müssen wir entweder ein neues Objekt instanziieren oder vorhandene Objekte verwenden. Sobald wir ein Objekt haben, können wir es verwenden, um die Ereignisse zu abonnieren.

Abbildung 7: Beendetes Ereignis für die Klasse System.Diagnostic.Process

Beendetes Ereignis für System.Diagnostic.Process Klasse in .NET

 

Beispiel: Behandlung von Process.Exited-Ereignissen in PowerShell

PowerShell bietet das Cmdlet "Register-ObjectEvent" zum Abonnieren von .NET-Framework-Ereignissen.

Angenommen, wir möchten das Ereignis "exiting" der Klasse Process abonnieren. Dazu benötigen wir zunächst ein Objekt der Klasse Process. Mit diesem Objekt können wir dann die Member-Ereignisse der Process-Klasse abonnieren.

Das Ereignis exiting wird aufgerufen, wenn ein Prozess beendet wird. In unserem Beispiel werden wir das Objekt calculator process verwenden, um das Ereignis exiting zu abonnieren.

Jeder unter Windows laufende Prozess ist ein Objekt. Um eine Liste der Prozessobjekte unter Windows zu erhalten, können wir die Get-CimInstance cmdlet. Wir sehen, Get-CimInstance gibt die Objekte zurück und kombiniert mit dem Get-Member Cmdlet können wir die Klassenmitglieder anzeigen:


Get-CimInstance 
[-ClassName]
[-ComputerName <string[]>]
[-KeyOnly]
[-Namespace]
[-OperationTimeoutSec ]
[-QueryDialect ]
[-Shallow ]
[-Filter ]
[-Property <string[]>]
[]

Quelle: Microsoft

Abbildung 8: Verwendung des Cmdlets Get-CimInstance zur Anzeige laufender Prozesse

Verwendung von Get-CimInstance Cmdlet zum Anzeigen laufender Prozesse

 

Für unser Beispiel starten wir in unserem Code den Taschenrechnerprozess. Wir haben immer die Möglichkeit, ein bereits vorhandenes Prozessobjekt zu verwenden. Im folgenden Code starten wir zunächst den Taschenrechnerprozess und erfassen das Objekt in der Variablen $CalcProcessObj.


$CalcProcessObj = [System.Diagnostics.Process]::Start("calc.exe") Register-ObjectEvent -InputObject 
$CalcProcessObj -EventName Exited -Action { cmd.exe /c ping -n 2 8.8.8.8 }

 

Als Nächstes verwenden wir das Cmdlet Register-ObjectEvent, um das Ereignis "Exited" für den Rechnerprozess zu abonnieren.


Register-ObjectEvent
[-InputObject]
[-EventName]
[[-SourceIdentifier]]
[[-Action]]
[-MessageData]
[-SupportEvent]
[-Forward]
[-MaxTriggerCount]
[]

Quelle: Microsoft

 

Wenn der Taschenrechnerprozess beendet wird, wird unser Aktionsblock ausgeführt. Der Aktionsblock enthält einen einfachen Befehl zum Senden von 2 Pings an die IP-Adresse 8.8.8.8.  

Das ist die Ausgabe, dass wir das Ereignis erfolgreich abonniert haben:

Abbildung 9: Ausgabe nach Ausführung des Cmdlets Register-ObjectEvent

Ausgabe nach der Ausführung des Cmdlets Register-ObjectEvent

 

Nachdem wir den Berechnungsprozess beendet haben, können wir sehen, dass der Action Script-Block ausgeführt wurde und dazu führte, dass 2 Pings an die IP-Adresse 8.8.8.8

gesendet wurden

Abbildung 10: Wireshark zeigt 2 Pings, die an die IP-Adresse 8.8.8.8 gesendet wurden

Wireshark zeigt 2 Pings, die an die IP-Adresse 8.8.8.8 gesendet wurden

 

Wie wir bereits gesehen haben, können wir das Cmdlet Get-EventSubscriber verwenden, um eine Liste aller Ereignisabonnements zu erhalten.

Die Ausgabe in unserem Beispiel ist hier zu sehen:

Abbildung 11: Liste der Ereignisabonnenten für die aktuelle Sitzung

Abrufen einer Liste von Ereignisabonnenten für die aktuelle Sitzung mit Get-EventSubscriber cmdlet

 

Ahnlich können wir das Cmdlet Unregister-Event verwenden, um die Registrierung eines Ereignisabonnements aufzuheben (ist die Verb-Nomen-Darstellung von Cmdlets nicht toll 😊), wie hier zu sehen ist:

Abbildung 12: Aufheben der Registrierung eines Ereignisabonnenten mit dem Cmdlet Unregister-Event

Aufheben der Registrierung eines Ereignisteilnehmers mit dem Cmdlet Unregister-Event

 

Beispiel: Behandlung von Ereignissen der Klasse FileSystemWatcher in PowerShell

Nehmen wir ein weiteres Beispiel für die FileSystemWatcher-Klasse mit einigen interessanten Events, die wir abonnieren können, wie z. B. die Erstellung oder Löschung von Dateien oder Verzeichnissen.

Angenommen, wir wollen das Erstellungsereignis von Dateien/Verzeichnissen abonnieren.

Wir folgen denselben Schritten wie in unserem letzten Beispiel:

  • Zuerst müssen wir das Objekt holen
  • Dann verwenden wir das Cmdlet Register-ObjectEvent, um das Ereignis zu abonnieren

 

Abbildung 13: Ereignisse für die Klasse FileSystemWatcher

Ereignisse für FileSystemWatcher Klasse in .NET

 

Erzeugen wir zunächst ein Objekt der FileSystemWatcher-Klasse


$testobj1 = New-Object -TypeName System.IO.FileSystemWatcher

 

Als Nächstes geben wir unserem Objekt den Verzeichnispfad, den es auf die Erstellung von Dateien/Verzeichnissen überwachen soll


$testobj1.Path =  "C:\Users\Public"

 

Zu guter Letzt verwenden wir das Cmdlet Register-ObjectEvent, um das Ereignis zu abonnieren.


Register-ObjectEvent -InputObject $testobj1 -EventName Created -Action { cmd.exe /c ping -n 2 8.8.8.8 }

 

 

Beispiel: Behandlung von Ereignissen der Klasse System.Diagnostics.EventLog in PowerShell

Hier ein weiteres Beispiel: die System.Diagnostics.EventLog-Klasse stellt ein Ereignis namens "EntryWritten" bereit, das ausgelöst wird, wenn ein Protokolleintrag geschrieben wird.

Wir folgen den gleichen Schritten wie zuvor: Wir instanziieren ein Objekt, setzen die Log-Eigenschaft für das Objekt (= welches Log wir beobachten wollen) und verwenden dann das Cmdlet Register-ObjectEvent, um das Ereignis EntryWritten zu abonnieren.


$testobj1 = New-Object -TypeName System.Diagnostics.EventLog

$testobj1.Log =  "Security"

Register-ObjectEvent -InputObject $testobj1 -EventName EntryWritten -Action { Write-Host  "Meow" }

 

Es ist zu beachten, dass dieser Code die Rechte eines Administrators erfordert, da wir mit der Protokollierung arbeiten.

EntryWritten event for EventLog class

EntryWritten-Ereignis für die EventLog-Klasse

 

Für diese Demonstration habe ich von VS Code zu ISE gewechselt. Wir haben das EntryWritten Event für Security Logs abonniert. Unsere Aktionsblöcke schreiben jedes Mal, wenn das Ereignis aufgerufen wird, "Meow".

Subscribing for “EntryWritten” event

Abonnement für das Ereignis "EintragGeschrieben" 

 

Zusammenfassung

Es gibt ein paar Dinge, die wir im Auge behalten müssen:

  • Ereignisse, Ereignisabonnements und die Ereigniswarteschlange existieren nur in der aktuellen Sitzung. Wenn wir die aktuelle Sitzung schließen, wird die Ereigniswarteschlange verworfen und das Ereignisabonnement abgebrochen.
  • Es gibt zwei separate Cmdlets für die Arbeit mit PowerShell-Engine-Ereignissen (Register-EngineEvent) und .NET Framework-Ereignissen (Register-ObjectEvent)

Meistere PowerShell WMI: überwache automatisiert System-Events ist der zweite Artikel zu diesem Thema.

 

Alle unsere Goodies für dich auf einer Seite: Active Directory, Graph, Teams, Exchange, PowerShell allgemein und mehr zum Thema Sicherheit

Dein ultimativer PowerShell-Spickzettel

Entfessele das volle Potenzial von PowerShell mit unserem praktischen Poster. Egal, ob frischer Einsteiger oder erfahrener Profi, dieser Spickzettel ist so konzipiert, dass du schnell die wichtigsten und am häufigsten verwendeten Cmdlets findest.

Das Poster ist zum Download und in Papierform erhältlich.

PowerShell Poster 2023

Hol dir hier dein Poster!

 

 

Weiterführende Links 

 

Zusammenhängende Posts

14 min read

Der Schlüssel zu produktiver Softwareverwaltung: winget & PowerShell

Steigere die IT-Effizienz mit Winget und PowerShell! Lies, wie du Installationen, Updates und die Verwaltung von...

9 min read

Diese 10 Aufgaben löst du perfekt mit PowerShell für Microsoft Purview

Mit Microsoft Purview verstehst und verwaltest du Daten in deinem gesamten Datenbestand – wie kannst du PowerShell...

17 min read

Nutze .NET in PowerShell für ereignisgesteuertes Scripting

Erweitere PowerShell mit .NET für eine leistungsstarke Ereignisautomatisierung. Systemereignisse wie ein Profi...

Über den Autor: