Was ist Windows PowerShell und was isst es? Teil 4: Arbeiten mit Objekten, benutzerdefinierte Klassen



Die Textausgabe von Befehlen im PowerShell-Interpreter-Fenster ist nur eine Möglichkeit, Informationen in einer für Menschen lesbaren Form anzuzeigen. Tatsächlich konzentriert sich die Umgebung auf die Arbeit mit Objekten: Cmdlets und Funktionen empfangen sie an der Eingabe und geben sie an der Ausgabe zurück , und die im interaktiven Modus und in Skripten verfügbaren Variablentypen basieren auf .NET-Klassen. Im vierten Artikel des Zyklus werden wir die Arbeit mit Objekten genauer untersuchen.

Inhaltsverzeichnis:


PowerShell




ForEach-Object, Group-Object Measure-Object
.NET COM (New-Object)

PSCustomObject


PowerShell


Denken Sie daran, dass ein Objekt eine Sammlung von Datenfeldern (Eigenschaften, Ereignisse usw.) und deren Verarbeitungsmethoden (Methoden) ist. Die Struktur wird durch den Typ bestimmt, der normalerweise auf den in der einheitlichen .NET Core-Plattform verwendeten Klassen basiert. Es ist auch möglich, mit COM-, CIM- (WMI) und ADSI-Objekten zu arbeiten. Eigenschaften und Methoden sind erforderlich, um verschiedene Aktionen für die Daten auszuführen. Zusätzlich zu PowerShell können Objekte als Argumente an Funktionen und Cmdlets übergeben, Variablen Werte zugewiesen werden und es gibt auch einen Mechanismus zum Erstellen von Befehlen (Pipeline oder Pipeline). Jeder Befehl in der Pipeline übergibt seine Ausgabe der Reihe nach an den nächsten - Objekt für Objekt. Für die Verarbeitung können Sie kompilierte Cmdlets verwenden oder eigene erweiterte Funktionen erstellenverschiedene Manipulationen mit Objekten in der Pipeline durchführen: Filtern, Sortieren, Gruppieren und sogar Ändern ihrer Struktur. Die Datenübertragung in dieser Form hat einen gravierenden Vorteil: Das empfangende Team muss den Bytestrom (Text) nicht analysieren, alle erforderlichen Informationen können einfach unter Bezugnahme auf die entsprechenden Eigenschaften und Methoden extrahiert werden.

Objektstruktur anzeigen


Führen Sie beispielsweise das Cmdlet Get-Process aus, mit dem Sie Informationen zu den im System ausgeführten Prozessen abrufen können:



Es werden einige formatierte Textdaten angezeigt, die keine Vorstellung von den Eigenschaften der zurückgegebenen Objekte und ihren Methoden vermitteln. Um die Ausgabe zu optimieren, müssen Sie lernen, wie Sie die Struktur von Objekten untersuchen. Das Cmdlet Get-Member hilft uns dabei:

Get-Process | Get-Member



Hier sehen wir bereits den Typ und die Struktur, und mit Hilfe zusätzlicher Parameter können wir beispielsweise nur die Eigenschaften des Objekts anzeigen, das die Eingabe eingegeben hat:

Get-Process | Get-Member -MemberType Property

Dieses Wissen wird benötigt, um administrative Aufgaben interaktiv zu lösen oder um eigene Skripte zu schreiben: Zum Beispiel, um Informationen über blockierte Prozesse von der Responding-Eigenschaft zu erhalten.

Objektfilterung


Mit PowerShell können Sie Objekte weiterleiten, die eine bestimmte Bedingung erfüllen:

Where-Object {   }

Das Ergebnis der Ausführung des Skriptblocks in Operator-Klammern sollte ein logischer Wert sein. Wenn es wahr ist ($ true), wird das Objekt, das in das Cmdlet Where-Object eingegeben wurde, an die Pipeline übergeben, andernfalls (der Wert $ false) wird es gelöscht. Zum Beispiel listen wir die gestoppten Windows Server-Dienste auf, d.h. diejenigen mit der Status-Eigenschaft auf Gestoppt:

Get-Service | Where-Object {$_.Status -eq "Stopped"}



Hier sehen wir wieder die Textdarstellung, aber wenn Sie den Typ und die interne Struktur der Objekte verstehen möchten, die die Pipeline durchlaufen, ist es einfach:

Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member



Objekte sortieren


Beim Pipelining von Objekten ist es häufig erforderlich, diese zu sortieren. Eigenschaftsnamen (Sortierschlüssel) werden an das Cmdlet Sort-Object übergeben und geben Objekte zurück, die nach ihren Werten geordnet sind. Die Ausgabe laufender Prozesse kann einfach nach der aufgewendeten Prozessorzeit (CPU-Eigenschaft) sortiert werden:

Get-Process | Sort-Object –Property cpu

Der Parameter -Property kann beim Aufrufen des Cmdlets Sort-Object weggelassen werden - er wird standardmäßig verwendet. Verwenden Sie für die umgekehrte Sortierung den Parameter -Descending:

Get-Process | Sort-Object cpu -Descending



Auswahl von Objekten und deren Teilen


Mit dem Cmdlet Select-Object können Sie eine bestimmte Anzahl von Objekten am Anfang oder am Ende einer Pipeline mithilfe der Parameter -First oder -Last auswählen. Damit können Sie einzelne Objekte oder bestimmte Eigenschaften auswählen sowie neue Objekte auf deren Basis erstellen. Wir werden die Arbeit des Cmdlets anhand einfacher Beispiele analysieren.

Der folgende Befehl zeigt Informationen zu 10 Prozessen an, die die maximale RAM-Größe (WS-Eigenschaft) verbrauchen:

Get-Process | Sort-Object WS -Descending | Select-Object -First 10



Sie können nur bestimmte Eigenschaften von Objekten auswählen, die die Pipeline durchlaufen, und auf ihrer Grundlage neue erstellen:

Get-Process | Select-Object ProcessName, Id -First 1

Als Ergebnis der Pipeline erhalten wir ein neues Objekt, dessen Struktur sich von der vom Cmdlet Get-Process zurückgegebenen Struktur unterscheidet. Wir werden dies mit Get-Member überprüfen:

Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member



Beachten Sie, dass Select-Object ein einzelnes Objekt (-First 1) zurückgibt, dessen nur zwei Felder von uns angegeben wurden: Ihre Werte wurden vom ersten Objekt kopiert, das mit dem Cmdlet Get-Process an die Pipeline übergeben wurde. Mit Select-Object können Sie unter anderem Objekte in PowerShell-Skripten erstellen:

$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType()



Mit Select-Object können Sie Objekten berechnete Eigenschaften hinzufügen, die als Hash-Tabelle dargestellt werden müssen . In diesem Fall entspricht der Wert des ersten Schlüssels dem Namen der Eigenschaft, und der Wert des zweiten Schlüssels entspricht dem Wert der Eigenschaft für das aktuelle Element der Pipeline:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}}



Schauen wir uns die Struktur der Objekte an, die die Pipeline durchlaufen:

Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member



Für jedes Objekt, Gruppenobjekt und Messobjekt


Es gibt andere Cmdlets zum Arbeiten mit Objekten. Zum Beispiel werden wir über die drei nützlichsten sprechen: Mit

ForEach-Object können Sie PowerShell-Code für jedes Objekt in der Pipeline ausführen:

ForEach-Object {   }

Group-Object - Gruppen - Objekte von Eigenschaftswert:

Group-Object PropertyName

Wenn Sie es mit dem Parameter -NoElement ausführen, können Sie die Anzahl der Elemente in Gruppen ermitteln.

Measure-Object aggregiert verschiedene Zusammenfassungsparameter anhand der Werte der Felder von Objekten in der Pipeline (berechnet die Summe und ermittelt auch den minimalen, maximalen oder durchschnittlichen Wert):

Measure-Object -Property PropertyName -Minimum -Maximum -Average -Sum

In der Regel werden die betrachteten Cmdlets interaktiv verwendet, und Skripte erstellen häufig Funktionen mit den Blöcken Begin, Process und End.

Erstellen von .NET- und COM-Objekten (neues Objekt)


Es gibt viele Softwarekomponenten mit .NET Core- und COM-Schnittstellen, die für Systemadministratoren nützlich sind. Mit der System.Diagnostics.EventLog-Klasse können Sie Systemprotokolle direkt in Windows PowerShell verwalten. Schauen wir uns ein Beispiel zum Erstellen einer Instanz dieser Klasse mit dem Cmdlet New-Object mit dem Parameter -TypeName an:

New-Object -TypeName System.Diagnostics.EventLog



Da wir kein bestimmtes Ereignisprotokoll angegeben haben, enthält die resultierende Instanz der Klasse keine Daten. Um dies zu ändern, müssen Sie während der Erstellung die spezielle Konstruktormethode mit dem Parameter -ArgumentList aufrufen. Wenn wir auf das Anwendungsprotokoll zugreifen möchten, übergeben Sie die Zeichenfolge "Anwendung" als Argument an den Konstruktor:

$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog



Bitte beachten Sie: Wir haben die Ausgabe des Befehls in der Variablen $ AppLog gespeichert. Obwohl Pipelines häufig im interaktiven Modus verwendet werden, erfordert die Skripterstellung häufig die Pflege einer Objektreferenz. Darüber hinaus sind die wichtigsten .NET Core-Klassen im System-Namespace enthalten: PowerShell sucht standardmäßig nach den darin angegebenen Typen, sodass das Schreiben von Diagnostics.EventLog anstelle von System.Diagnostics.EventLog völlig korrekt ist.

Um mit dem Journal zu arbeiten, können Sie auf die entsprechenden Methoden verweisen:

$AppLog | Get-Member -MemberType Method



Angenommen, es wird mit der Clear () -Methode mit Zugriffsrechten gelöscht:

$AppLog.Clear()

Das Cmdlet New-Object wird auch zum Arbeiten mit COM-Komponenten verwendet. Es gibt ziemlich viele davon - von den mit dem Windows-Skriptserver gelieferten Bibliotheken bis zu ActiveX-Anwendungen wie beispielsweise Internet Explorer. Um ein COM-Objekt zu erstellen, müssen Sie den Parameter -ComObject mit der Programmkennung ProgId der gewünschten Klasse angeben:

New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject

Um eigene Objekte mit einer beliebigen Struktur zu erstellen, wirkt die Verwendung von New-Object zu archaisch und umständlich. Dieses Cmdlet wird für die Arbeit mit Softwarekomponenten außerhalb von PowerShell verwendet. In den folgenden Artikeln wird dieses Problem ausführlicher behandelt. Neben .NET- und COM-Objekten lernen wir auch CIM- (WMI) und ADSI-Objekte kennen.

Statische Methoden aufrufen


Es ist nicht möglich, Instanzen einiger .NET Core-Klassen zu erstellen. Dazu gehören System.Environment und System.Math. Sie sind statisch und enthalten nur statische Eigenschaften und Methoden. Im Wesentlichen handelt es sich hierbei um Referenzbibliotheken, die verwendet werden, ohne Objekte zu erstellen. Sie können durch ein Literal auf eine statische Klasse verweisen, wobei der Typname in eckige Klammern eingeschlossen wird. Wenn Sie sich die Struktur des Objekts mit Get-Member ansehen, sehen Sie außerdem den Typ System.RuntimeType anstelle von System.Environment:

[System.Environment] | Get-Member



Um nur statische Elemente anzuzeigen, müssen Sie Get-Member mit dem Parameter -Static aufrufen (achten Sie auf den Objekttyp):

[System.Environment] | Get-Member -Static



Für den Zugriff auf statische Eigenschaften und Methoden werden zwei aufeinanderfolgende Doppelpunkte anstelle eines Punkts nach einem Literal verwendet:

[System.Environment]::OSVersion

Oder

$test=[System.Math]::Sqrt(25) 
$test
$test.GetType()



Geben Sie PSCustomObject ein


Unter den vielen in PowerShell verfügbaren Datentypen ist PSCustomObject zu erwähnen, mit dem Objekte mit einer beliebigen Struktur gespeichert werden können. Das Erstellen eines solchen Objekts mit dem Cmdlet "New-Object" wird als klassische, aber umständliche und veraltete Methode angesehen:

$object = New-Object  –TypeName PSCustomObject -Property @{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'}

Schauen wir uns die Struktur des Objekts an:

$object | Get-Member



Ab PowerShell 3.0 steht eine andere Syntax zur Verfügung:

$object = [PSCustomObject]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

Sie können auf eine der folgenden Arten auf die Daten zugreifen:

$object.Name

$object.'Name'

$value = 'Name'
$object.$value

Hier ist ein Beispiel für die Konvertierung einer vorhandenen Hash-Tabelle in ein Objekt:

$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()



Einer der Nachteile von Objekten dieses Typs besteht darin, dass sich die Reihenfolge ihrer Eigenschaften ändern kann. Um dies zu vermeiden, müssen Sie das Attribut [geordnet] verwenden:

$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko'; 
                                          City = 'Moscow';
                                          Country = 'Russia'
}

Es gibt andere Möglichkeiten, ein Objekt zu erstellen: Oben haben wir die Verwendung des Cmdlets Select-Object untersucht . Es bleibt das Hinzufügen und Entfernen von Elementen zu behandeln. Dies für das Objekt aus dem vorherigen Beispiel zu tun, ist ganz einfach:

$object | Add-Member –MemberType NoteProperty –Name Age  –Value 33
$object | Get-Member



Mit dem Cmdlet Add-Member können Sie dem zuvor erstellten $ object-Objekt nicht nur Eigenschaften, sondern auch Methoden hinzufügen, indem Sie das Konstrukt "-MemberType ScriptMethod" verwenden:

$ScriptBlock = {
    #  
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member

Hinweis: Um den Code für die neue Methode zu speichern, haben wir die Variable $ ScriptBlock vom Typ ScriptBlock verwendet.



Verwenden Sie die entsprechende Methode, um Eigenschaften zu entfernen:

$object.psobject.properties.remove('Name')

Eigene Klassen erstellen


PowerShell 5.0 bietet die Möglichkeit, Klassen mithilfe der charakteristischen Syntax für objektorientierte Programmiersprachen zu definieren . Hierfür ist das Dienstwort Class vorgesehen. Danach sollten Sie den Klassennamen angeben und seinen Text in Operator-Klammern beschreiben:

class MyClass
{
    #  
}

Dies ist ein echter Typ von .NET Core, dessen Hauptteil seine Eigenschaften, Methoden und andere Elemente beschreibt. Betrachten Sie ein Beispiel für eine einfache Klassendefinition:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
}

Verwenden Sie zum Erstellen eines Objekts (einer Instanz einer Klasse) das Cmdlet New-Object oder ein Literal vom Typ [MyClass] und die pseudostatische neue Methode (Standardkonstruktor):

$object = New-Object -TypeName MyClass

oder

$object = [MyClass]::new()

Analysieren wir die Struktur des Objekts:

$object | Get-Member



Vergessen Sie nicht den Gültigkeitsbereich: Sie können den Typnamen nicht als Zeichenfolge bezeichnen oder ein Typliteral außerhalb des Skripts oder Moduls verwenden, in dem die Klasse definiert ist. Gleichzeitig können Funktionen Instanzen der Klasse (Objekte) zurückgeben, die außerhalb des Moduls oder Skripts verfügbar sind.

Geben Sie nach dem Erstellen des Objekts seine Eigenschaften ein:

$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object



Beachten Sie, dass in der Klassenbeschreibung nicht nur Eigenschaftstypen festgelegt werden, sondern auch deren Standardwerte:

class Example
{
     [string]$Name = 'John Doe'
}

Die Beschreibung der Klassenmethode ähnelt der Beschreibung einer Funktion, jedoch ohne Verwendung der Funktionswortfunktion. Wie in der Funktion werden die Parameter bei Bedarf an die Methoden übergeben:

class MyClass 
{
     [string]$Name
     [string]$City
     [string]$Country
     
     # 
     Smile([bool]$param1)
     {
         If($param1) {
            Write-Host ':)'
         }
     }
}

Jetzt kann der Vertreter unserer Klasse lächeln:

$object = [MyClass]::new()
$object.Smile($true)

Methoden können überladen werden. Darüber hinaus verfügt die Klasse über statische Eigenschaften und Methoden sowie über Konstruktoren, deren Namen mit dem Namen der Klasse selbst übereinstimmen. Eine in einem Skript oder PowerShell-Modul definierte Klasse kann als Basis für eine andere Klasse dienen - so wird die Vererbung implementiert. Gleichzeitig ist die Verwendung vorhandener .NET-Klassen als Basis zulässig:

class MyClass2 : MyClass
{
      #  ,     MyClass
}
[MyClass2]::new().Smile($true)

Unsere Beschreibung der Arbeit mit Objekten in PowerShell ist kaum erschöpfend. In den folgenden Veröffentlichungen werden wir versuchen, dies anhand praktischer Beispiele zu vertiefen: Der fünfte Artikel der Reihe befasst sich mit den Fragen der Integration von PowerShell in Softwarekomponenten von Drittanbietern. Frühere Teile finden Sie unter den folgenden Links.



1: Windows PowerShell
2: Windows PowerShell
3: ,


All Articles