Die Textausgabe von Befehlen im PowerShell-Interpreterfenster ist lediglich eine Möglichkeit, Informationen in einer für die menschliche Wahrnehmung geeigneten Form darzustellen. Eigentlich Mittwoch um mit Objekten zu arbeiten: Cmdlets und Funktionen empfangen sie als Eingabe und , und die interaktiv und in Skripten verfügbaren Variablentypen basieren auf .NET-Klassen. Im vierten Artikel der Serie gehen wir näher auf die Arbeit mit Objekten ein.
Table of Contents:
Objekte in PowerShell
Erinnern wir uns daran, dass ein Objekt eine Sammlung von Datenfeldern (Eigenschaften, Ereignisse usw.) und Methoden zu deren Verarbeitung (Methoden) ist. Seine Struktur wird durch einen Typ angegeben, der normalerweise auf Klassen basiert, die in der einheitlichen .NET Core-Plattform verwendet werden. Es ist auch möglich, mit COM-, CIM- (WMI) und ADSI-Objekten zu arbeiten. Eigenschaften und Methoden werden benötigt, um verschiedene Aktionen an Daten auszuführen. Darüber hinaus können in PowerShell Objekte als Argumente an Funktionen und Cmdlets übergeben, ihre Werte Variablen zugewiesen werden, und das ist auch möglich (Förderband oder Rohrleitung). Jeder Befehl in der Pipeline gibt seine Ausgabe der Reihe nach Objekt für Objekt an den nächsten weiter. Zur Verarbeitung können Sie kompilierte Cmdlets verwenden oder eigene erstellen um verschiedene Manipulationen mit Objekten in der Pipeline durchzuführen: Filtern, Sortieren, Gruppieren und sogar Ändern ihrer Struktur. Die Übertragung von Daten in dieser Form hat einen gravierenden Vorteil: Das empfangende Team muss den Bytestrom (Text) nicht analysieren, alle erforderlichen Informationen können einfach durch Aufrufen der entsprechenden Eigenschaften und Methoden abgerufen werden.
Anzeigen der Struktur von Objekten
Lassen Sie uns beispielsweise das Cmdlet Get-Process ausführen, mit dem Sie Informationen über die im System ausgeführten Prozesse abrufen können:

Es werden einige formatierte Textdaten angezeigt, die keinen Aufschluss über die Eigenschaften der zurückgegebenen Objekte und ihrer Methoden geben. Um die Ausgabe zu optimieren, müssen wir lernen, die Struktur von Objekten zu untersuchen, und das Cmdlet „Get-Member“ wird uns dabei helfen:
Get-Process | Get-Member 
Hier sehen wir bereits den Typ und die Struktur und können mit Hilfe zusätzlicher Parameter beispielsweise nur die Eigenschaften des in der Eingabe enthaltenen Objekts anzeigen:
Get-Process | Get-Member -MemberType PropertyDieses Wissen wird benötigt, um Verwaltungsprobleme interaktiv zu lösen oder eigene Skripte zu schreiben, beispielsweise um Informationen über blockierte Prozesse mithilfe der Responding-Eigenschaft zu erhalten.
Objekte filtern
PowerShell ermöglicht die Weiterleitung von Objekten, die eine bestimmte Bedingung erfüllen, durch eine Pipeline:
Where-Object { блок сценария }Das Ergebnis der Ausführung des Skriptblocks innerhalb der Operatorklammern muss ein boolescher Wert sein. Ist er wahr ($true), wird das an das Where-Object-Cmdlet übergebene Objekt in der Pipeline weitergegeben; andernfalls (Wert $false) wird es gelöscht. Beispiel: Wir zeigen eine Liste der gestoppten Dienste an. Windows Server, d.h. diejenigen, deren Status-Eigenschaft den Wert „Gestoppt“ hat:
Get-Service | Where-Object {$_.Status -eq "Stopped"} 
Auch hier sehen wir eine Textdarstellung, aber wenn Sie den Typ und die interne Struktur der Objekte verstehen möchten, die die Pipeline durchlaufen, ist dies nicht schwierig:
Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member 
Objekte sortieren
Bei der Pipeline-Verarbeitung von Objekten besteht häufig die Notwendigkeit, diese zu sortieren. Dem Cmdlet Sort-Object werden die Namen von Eigenschaften (Sortierschlüssel) übergeben und es gibt Objekte geordnet nach ihren Werten zurück. Es ist einfach, die Ausgabe laufender Prozesse nach der verbrauchten CPU-Zeit zu sortieren (CPU-Eigenschaft):
Get-Process | Sort-Object –Property cpuDer Parameter -Property kann beim Aufruf 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 
Auswählen von Objekten und deren Teilen
Mit dem Cmdlet „Select-Object“ können Sie mithilfe der Parameter „-First“ oder „-Last“ eine bestimmte Anzahl von Objekten am Anfang oder Ende einer Pipeline auswählen. Mit seiner Hilfe können Sie einzelne Objekte oder bestimmte Eigenschaften auswählen und darauf basierend auch neue Objekte erstellen. Schauen wir uns anhand einfacher Beispiele an, wie das Cmdlet funktioniert.
Der folgende Befehl zeigt Informationen zu den 10 Prozessen an, die die maximale Menge an RAM verbrauchen (WS-Eigenschaft):
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 darauf basierend neue erstellen:
Get-Process | Select-Object ProcessName, Id -First 1Als Ergebnis des Pipeline-Vorgangs erhalten wir ein neues Objekt, dessen Struktur sich von der vom Cmdlet Get-Process zurückgegebenen Struktur unterscheidet. Überprüfen wir dies mit Get-Member:
Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member 
Beachten Sie, dass Select-Object ein einzelnes Objekt (-First 1) zurückgibt, das nur zwei der von uns angegebenen Felder enthält: Ihre Werte wurden vom ersten Objekt kopiert, das vom Cmdlet Get-Process an die Pipeline übergeben wurde. Eine Möglichkeit zum Erstellen von Objekten in PowerShell-Skripten basiert auf der Verwendung von Select-Object:
$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType() 
Mit Select-Object können Sie berechnete Eigenschaften zu Objekten hinzufügen, als die dargestellt werden müssen . In diesem Fall entspricht der Wert seines ersten Schlüssels dem Eigenschaftsnamen und der Wert des zweiten Schlüssels dem Eigenschaftswert für das aktuelle Pipelineelement:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} 
Schauen wir uns die Struktur von Objekten an, die das Förderband passieren:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member 
ForEach-Object, Group-Object und Measure-Object
Für die Arbeit mit Objekten gibt es weitere Cmdlets. Lassen Sie uns als Beispiel über die drei nützlichsten sprechen:
Für jedes Objekt ermöglicht es Ihnen, PowerShell-Code für jedes Objekt in der Pipeline auszuführen:
ForEach-Object { блок сценария }Gruppenobjekt gruppiert Objekte nach Eigenschaftswert:
Group-Object PropertyNameWenn Sie es mit dem Parameter -NoElement ausführen, können Sie die Anzahl der Elemente in den Gruppen ermitteln.
Messobjekt aggregiert verschiedene Zusammenfassungsparameter nach Objektfeldwerten in der Pipeline (berechnet die Summe und ermittelt auch den Minimal-, Maximal- oder Durchschnittswert):
Measure-Object -Property PropertyName -Minimum -Maximum -Average -SumTypischerweise werden die besprochenen Cmdlets interaktiv verwendet und oft in Skripten erstellt. mit Begin-, Process- und End-Blöcken.
Erstellen von .NET- und COM-Objekten (New-Object)
Es gibt zahlreiche Softwarekomponenten mit .NET Core- und COM-Schnittstellen, die für Systemadministratoren nützlich sind. Mithilfe der Klasse `System.Diagnostics.EventLog` können Sie Systemprotokolle direkt verwalten. Windows PowerShell. Sehen wir uns ein Beispiel für die Erstellung einer Instanz dieser Klasse mithilfe des Cmdlets New-Object mit dem Parameter -TypeName an:
New-Object -TypeName System.Diagnostics.EventLog 
Da wir kein spezifisches Ereignisprotokoll angegeben haben, enthält die resultierende Instanz der Klasse keine Daten. Um dies zu ändern, müssen Sie bei der Erstellung eine spezielle Konstruktormethode mit dem Parameter -ArgumentList aufrufen. Wenn wir auf das Anwendungsprotokoll zugreifen möchten, sollten wir die Zeichenfolge „Application“ als Argument an den Konstruktor übergeben:
$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog 
Bitte beachten Sie, dass wir die Ausgabe des Befehls in der Variablen $AppLog gespeichert haben. Obwohl Pipelines häufig im interaktiven Modus verwendet werden, erfordert das Schreiben von Skripts häufig die Pflege eines Verweises auf ein Objekt. Darüber hinaus sind die .NET Core-Kernklassen im System-Namespace enthalten: PowerShell sucht darin standardmäßig nach bestimmten Typen, daher ist es völlig korrekt, Diagnostics.EventLog anstelle von System.Diagnostics.EventLog zu schreiben.
Um mit dem Protokoll zu arbeiten, können Sie die entsprechenden Methoden verwenden:
$AppLog | Get-Member -MemberType Method 
Nehmen wir an, es wird durch die Clear()-Methode gelöscht, wenn Zugriffsrechte vorhanden sind:
$AppLog.Clear()Das Cmdlet „New-Object“ wird auch zur Arbeit mit COM-Komponenten verwendet. Davon gibt es eine ganze Reihe, die aus den mit dem Server gelieferten Skripten stammen. Windows Bibliotheken für ActiveX-Anwendungen wie Internet Explorer. Um ein COM-Objekt zu erstellen, müssen Sie den Parameter -ComObject mit der 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.FileSystemObjectUm eigene Objekte mit beliebiger Struktur zu erstellen, erscheint die Verwendung von New-Object zu archaisch und umständlich; dieses Cmdlet wird verwendet, um mit Softwarekomponenten außerhalb von PowerShell zu arbeiten. In zukünftigen Artikeln wird dieses Thema detaillierter besprochen. Zusätzlich zu .NET- und COM-Objekten werden wir auch CIM- (WMI) und ADSI-Objekte untersuchen.
Statische Methoden aufrufen
Einige .NET Core-Klassen können nicht instanziiert werden, einschließlich System.Environment und System.Math. Sie sind und enthalten nur statische Eigenschaften und Methoden. Hierbei handelt es sich im Wesentlichen um Referenzbibliotheken, die ohne Erstellung von Objekten verwendet werden. Sie können über ein Literal auf eine statische Klasse verweisen, indem Sie den Typnamen in eckige Klammern setzen. Wenn wir uns jedoch die Struktur des Objekts mit Get-Member ansehen, sehen wir den Typ System.RuntimeType anstelle von System.Environment:
[System.Environment] | Get-Member 
Um nur statische Mitglieder anzuzeigen, rufen Sie Get-Member mit dem Parameter -Static auf (beachten Sie den Objekttyp):
[System.Environment] | Get-Member -Static 
Um auf statische Eigenschaften und Methoden zuzugreifen, verwenden Sie zwei aufeinanderfolgende Doppelpunkte anstelle eines Punkts nach dem Literal:
[System.Environment]::OSVersionOder
$test=[System.Math]::Sqrt(25)
$test
$test.GetType() 
Geben Sie PSCustomObject ein
Unter den zahlreichen in PowerShell verfügbaren Datentypen ist PSCustomObject erwähnenswert, das zum Speichern von Objekten mit beliebiger Struktur entwickelt wurde. Das Erstellen eines solchen Objekts mit dem Cmdlet New-Object gilt als klassische, aber umständliche und veraltete Methode:
$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 ist eine andere Syntax verfügbar:
$object = [PSCustomObject]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Sie können auf eine der entsprechenden Arten auf die Daten zugreifen:
$object.Name
$object.'Name'
$value = 'Name'
$object.$value
Hier ist ein Beispiel für die Konvertierung einer vorhandenen Hashtabelle in ein Objekt:
$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()

Einer der Nachteile von Objekten dieser Art besteht darin, dass sich die Reihenfolge ihrer Eigenschaften ändern kann. Um dies zu vermeiden, müssen Sie das Attribut [ordered] verwenden:
$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Es gibt andere Möglichkeiten, ein Objekt zu erstellen: Oben haben wir uns die Verwendung des Cmdlets angesehen . Jetzt müssen Sie nur noch das Hinzufügen und Entfernen von Elementen herausfinden. Für das Objekt aus dem vorherigen Beispiel ist dies ganz einfach:
$object | Add-Member –MemberType NoteProperty –Name Age –Value 33
$object | Get-Member

Mit dem Cmdlet „Add-Member“ können Sie nicht nur Eigenschaften, sondern auch Methoden zu einem zuvor erstellten $object hinzufügen, indem Sie das Konstrukt „-MemberType ScriptMethod“ verwenden:
$ScriptBlock = {
# код
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member
Bitte beachten Sie, dass wir die Variable $ScriptBlock vom Typ ScriptBlock verwendet haben, um den Code für die neue Methode zu speichern.

Um Eigenschaften zu entfernen, verwenden Sie die entsprechende Methode:
$object.psobject.properties.remove('Name')
Erstellen Sie Ihre eigenen Klassen
Mit PowerShell 5.0 wurde die Möglichkeit zum Definieren eingeführt Verwendung der für objektorientierte Programmiersprachen charakteristischen Syntax. Dafür ist das Dienstwort Class vorgesehen, danach sollten Sie den Namen der Klasse angeben und ihren Rumpf in Operatorklammern beschreiben:
class MyClass
{
# тело класса
}
Dies ist ein echter .NET Core-Typ mit einem Hauptteil, der seine Eigenschaften, Methoden und anderen Elemente beschreibt. Schauen wir uns ein Beispiel für die Definition der einfachsten Klasse an:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
}
Um ein Objekt (Klasseninstanz) zu erstellen, verwenden Sie das Cmdlet oder ein Literal vom Typ [MyClass] und new (Standardkonstruktor):
$object = New-Object -TypeName MyClassoder
$object = [MyClass]::new()Lassen Sie uns die Struktur des Objekts analysieren:
$object | Get-Member 
Vergessen Sie nicht den Gültigkeitsbereich: Sie können einen Typnamen nicht als Zeichenfolge bezeichnen oder ein Typliteral außerhalb des Skripts oder Moduls verwenden, in dem die Klasse definiert ist. In diesem Fall können Funktionen Klasseninstanzen (Objekte) zurückgeben, auf die außerhalb des Moduls oder Skripts zugegriffen werden kann.
Geben Sie nach dem Erstellen des Objekts seine Eigenschaften ein:
$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object

Beachten Sie, dass die Klassenbeschreibung nicht nur die Eigenschaftstypen, sondern auch deren Standardwerte angibt:
class Example
{
[string]$Name = 'John Doe'
}
Die Beschreibung einer Klassenmethode ähnelt der Beschreibung einer Funktion, jedoch ohne die Verwendung des Funktionsworts. Wie bei einer Funktion werden bei Bedarf Parameter an 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 sein; außerdem ist eine Klasse überladen sowie 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. In diesem Fall ist es erlaubt, vorhandene .NET-Klassen als Basis zu verwenden:
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, es anhand praktischer Beispiele zu vertiefen: Der fünfte Artikel der Reihe widmet sich den Fragen der Integration von PowerShell mit Softwarekomponenten von Drittanbietern. Frühere Teile finden Sie unter den folgenden Links.
Source: habr.com
