| | 0

PowerShell: Objekte, Objekteigenschaften und –Methoden, Objektverarbeitung – Part 6

3.7    Objekte, Objekteigenschaften und –Methoden, Objektverarbeitung

Die wohl  revolutionärste Idee, die den Einzug in PowerShell gefunden hat, ist die Verwendung von Objekten. Fast alles in der PowerShell wird durch (.Net) Objekte repräsentiert. Was bedeutet das genau? Ein Beispiel sollte helfen… Sowohl in der CMD wie auch in der PS kann der Befehl „dir“ zur Auflistung von Verzeichnisinhalten verwendet werden (natürlich ist das in der PowerShell nur ein Alias…). Die Ausgabe des Befehls auf dem Bildschirm kann ähnlich oder gar identisch sein. Innerhalb der CMD kann höchstens mit Hilfe der For-Schleife die Ausgabe noch etwas verarbeitet werden. Die Elemente sind jedoch reiner Text (Strings). Mit normalen Mitteln können nur sehr schwer weitere Informationen über die aufgelisteten Dateien eingeholt werden (meist sind externe Werkzeuge notwendig). Soll z.B. das Datum der letzten Änderung einer Datei oder eines Verzeichnisses ermittelt werden, müssen komplizierte und vor Allem schwer lesbare Konstrukte verwendet werden, wie z.B. hier:

for /f " usebackq tokens=1" %i in (`dir ^| find /i "Music"`) do echo %i</pre>
21.08.2010

Das könnte noch hingenommen werden, aber was ist mit den Eigenschaften, welche mit Hilfe des Befehls „dir“ gar nicht auf dem Bildschirm angezeigt werden, wie z.B. das Erstellungsdatum? Hmmm, ohne externe Werkzeuge wird das wohl nicht machbar sein…
Die PowerShell verhält sich an dieser Stelle völlig anders. Es wird zwar möglicherweise Ähnliches angezeigt, wie in der CMD, aber es stehen dennoch wesentlich mehr Informationen und Möglichkeiten zur Verfügung. Das geschieht dadurch, weil die PowerShell für jeden Verzeichniseintrag ein Objekt erzeugt…

Exkurs: objektorientiertes Programmieren
Das objektorientierte Programmieren fängt mit einer Klasse an. Eine Klasse beschreibt sog. Eigenschaften und Methoden eines künftigen Objektes. Nehmen wir mal an, wir definieren eine Klasse mit dem Namen „Auto“. Fast jedes Auto braucht Räder (welche wiederum eine andere Klasse sind oder sein können), deren Anzahl oder die Reifenbreite Eigenschaften ist. Eine andere Eigenschaft könnte z.B. die Autofarbe oder die Fahrgeschwindigkeit sein. Fährt ein Auto an, muss Gas gegeben werden, zum Anhalten muss gebremst werden. Dies wären Methoden, die auf das Auto angewendet werden können (beschleunigen, bremsen). Mit der Klasse „Auto“ kann allerdings noch nicht gefahren werden. Die Anzahl der Räder ist nicht bekannt, genauso, wie die Farbe. Um dies tun zu können, muss eine Klasse instanziiert werden: das Auto muss gebaut werden. Eine Instanz einer Klasse hat dann „physikalische“ Räder, die gezählt werden können. Wenn auf das Auto die Methode „Beschleunigen“ angewendet wird, ändert sich auch die Fahrtgeschwindigkeit, genauso, wie beim Bremsen. In der Regel kann also zu jedem Zeit-punkt jede Eigenschaft ermittelt und bestimmte Methoden können angewendet werden. Das Objekt „lebt“ sozusagen…

…, mit all seinen Eigenschaften und Methoden. Zurück zum ursprünglichen Beispiel, diesmal mit einer PS Lösung:

1.  $(get-childitem | Where-Object {$_.name -like "music"}).creationtime

Montag, 21. Dezember 2009 16:18:49

Somit ist sogar der in einer CMD unmögliche Teil erledigt: es wird das Erstellungsdatum des Eintrages ausgegeben! Zugegebenermaßen sieht die obige Zeile auf den ersten Blick nicht viel besser aus, als das der Fall in der CMD war. Dies wird sich jedoch hoffentlich im Laufe der Zeit ändern.

Wie können die Eigenschaften und Methoden eines PS Objektes angezeigt und verwendet werden? Das Cmdlet Get-Member ist eigens dazu entwickelt, Informationen über einzelne Objekte zu liefern. Je nach Art des Objektes werden natürlich unterschiedliche Informationen ausgegeben, da jede Klasse eigene Eigenschaften und Methoden definiert. Das kann am Beispiel eines Strings veranschaulicht werden:

$MyString = "abc-cde-def"

get-member -InputObject $MyString

TypeName: System.String

Name             MemberType            Definition

----             ----------            ----------

Clone            Method                System.Object Clone()

CompareTo        Method                int CompareTo(System.Object value), …

Contains         Method                bool Contains(string value)

CopyTo           Method                System.Void CopyTo(int sourceIndex, …

EndsWith         Method                bool EndsWith(string value), bool En…

Equals           Method                bool Equals(System.Object obj), bool…

GetEnumerator    Method                System.CharEnumerator GetEnumerator(…

GetHashCode      Method                int GetHashCode()

GetType          Method                type GetType()

GetTypeCode      Method                System.TypeCode GetTypeCode()

IndexOf          Method                int IndexOf(char value), int IndexOf…

IndexOfAny       Method                int IndexOfAny(char[] anyOf), int In…

Insert           Method                string Insert(int startIndex, string…

IsNormalized     Method                bool IsNormalized(), bool IsNormaliz…

LastIndexOf      Method                int LastIndexOf(char value), int Las…

LastIndexOfAny   Method                int LastIndexOfAny(char[] anyOf), in…

Normalize        Method                string Normalize(), string Normalize…

PadLeft          Method                string PadLeft(int totalWidth), stri…

PadRight         Method                string PadRight(int totalWidth), str…

Remove           Method                string Remove(int startIndex, int co…

Replace          Method                string Replace(char oldChar, char ne…

Split            Method                string[] Split(Params char[] separat…

StartsWith       Method                bool StartsWith(string value), bool …

Substring        Method                string Substring(int startIndex), st…

ToCharArray      Method                char[] ToCharArray(), char[] ToCharA…

ToLower          Method                string ToLower(), string ToLower(Sys…

ToLowerInvariant Method                string ToLowerInvariant()

ToString         Method                string ToString(), string ToString(S…

ToUpper          Method                string ToUpper(), string ToUpper(Sys…

ToUpperInvariant Method                string ToUpperInvariant()

Trim             Method                string Trim(Params char[] trimChars)…

TrimEnd          Method                string TrimEnd(Params char[] trimCha…

TrimStart        Method                string TrimStart(Params char[] trimC…

Chars            ParameterizedProperty char Chars(int index) {get;}

Length           Property              System.Int32 Length {get;}

In der Spalte „Name“ wird der Name der jeweiligen Eigenschaft oder Methode angezeigt. Die Spalte „MemberType“ informiert darüber, ob der Eintrag eine Methode oder eine Eigenschaft ist (andere MemberTypen sind an der Stelle irrelevant). In der Spalte „Definition“ wird der Typ des Resultats angezeigt, gefolgt von einer möglichen Verwendungssyntax. Der Zugriff auf die Methoden und Eigenschaften eines Objektes erfolgt mit Hilfe sog. Punktnotation. Hinter dem Namen des Objektes wird ein Punkt geschrieben, gefolgt von dem Namen der Methode oder Eigenschaft:

</pre>
$MyString.Length

11
<pre>

Wenn eine Methode eines Objektes angewendet werden soll, muss hinter dem Namen der Methode ein Klammerpaar stehen. Für Methoden, welche Argumente brauchen, werden diese innerhalb der Klammern geschrieben:

$MyString.GetHashCode()

732858657

$MyString.Split("-")

abc

cde

def

>

Die oben angewendete Methode „Split“ verändert den Wert der Variablen $MyString nicht, sondern gibt das Ergebnis als ein weiteres Objekt aus. Dieses Objekt kann direkt weiter verarbeitet werden oder einer Variablen zugewiesen werden. Soll das Objekt direkt weiter verarbeitet werden, ohne eine zusätzliche Variable erzeugen zu wollen, geschieht das meistens mit Hilfe der sog. Pipeline. Der Begriff Pipeline ist wesentlich älter als die PowerShell. Pipelines werden in fast jeder Shell verwendet, so auch in der CMD. Etwas „durch“ die Pipeline zu schicken bedeutet einfach, dass die Ergebnisse eines Befehls direkt an einen anderen Befehl übergeben werden. In der CMD kann das z.B. so aussehen:

dir | sort /R

Die Ausgabe des Befehls „dir“ wird über die Pipeline an den Befehl „sort“ weiter geleitet. Als Resultat erscheint in diesem Fall der Inhalt des aktuellen Verzeichnisses, absteigend sortiert. Das Resultat ist hier aber ebenfalls reiner Text, so wie auch beim Befehl „dir“. In der PowerShell wird das Ergebnis eines Befehls, also ein Objekt, durch die Pipeline geschickt und an einen anderen Befehl übergeben, ohne sein Wesen als Objekt zu verlieren! Das heißt, auch hinter der Pipeline kann auf Eigenschaften und Methoden zugegriffen werden:

dir | Where-Object {$_.creationtime -gt "01.06.2010"} | Foreach-Object {$_.lastaccesstime}

Mittwoch, 15. September 2010 19:20:02

Dienstag, 19. Januar 2010 20:16:13

Sonntag, 18. April 2010 11:06:40

Dienstag, 23. Februar 2010 13:43:18

Mittwoch, 1. Dezember 2010 09:03:52

Donnerstag, 14. Oktober 2010 09:39:37

Im diesem Beispiel listet der „dir“ Befehl (Alias für Get-ChildItem in der PowerShell) den Inhalt des aktuellen Verzeichnisses. Das Ergebnis von 17 Einträgen wird über die Pipeline auf den Befehl Where-Object gesendet. Das Cmdlet Where-Object bietet unter anderem die Möglichkeit, aus einer Sammlung von Objekten diejenigen zu wählen, deren Eigenschaften bestimmten Kriterien entsprechen. Wenn, wie in diesem Beispiel, mehrere Objekte durch die Pipeline geschickt werden, werden sie durch den Befehl hinter der Pipeline nacheinander abgearbeitet. In diesem Konstrukt repräsentiert die Variable $_ das jeweils gerade bearbeitete Objekt. Für jeden Eintrag in dem aktuellen Verzeichnis wird also nach der ersten Pipeline geprüft, ob das Erstellungsdatum ($_.creationtime) größer ist (-gt = grater then, siehe Kapitel 3.9.3), als 01.06.2010. Dieser Schritt reduziert die ursprüngliche Anzahl von Einträgen auf diejenigen, welche die genannte Bedingung erfüllen und sendet das Ergebnis (immerhin noch 6 Einträge) über eine weitere Pipeline an das Cmdlet Foreach-Object. Dieses Cmdlet erlaubt es, für jedes übergebene Objekt die Aktion in den geschweiften Klammern auszuführen. In diesem Fall ist das die Ausgabe der Eigenschaft „lastaccesstime“, also die Zeit des letzten Zugriffes auf den jeweiligen Eintrag im Dateisystem.

Zurück zu Part 5 – Befehle = CMDlets, Aliase, externe Befehle, PSSnapins und Hilfe

Weiter zu Part 7 – Datentypen allgemein

Zur Übersicht aller Artikel dieser Windows PowerShell Blogserie.