.. index:: Pipeline Pipeline ******** Die Pipeline verbindet eine Vielzahl von Befehlen zusammen; das Ergebnis eine Befehls wird als Eingabewert für den nächsten Befehl verwendet, solange, bis das gewünschte Ergebnis erreicht ist. test .. image:: images/pipeline_1.jpg .. image:: images/pipeline_2.jpg .. image:: images/pipeline_3.jpg Während es auch schon zu DOS-Zeiten das Konzept des Pipens gab und auch Unix-Shells heftig davon Gebrauch machen, gibt es doch einen gravierenden Unterschied zu diesen alten Implementierungen. Während in der alten Zeit Strings als Tauschformat benutzt wurden, verwendet die Powershell echte Objekte. Die Eigenschaften und Methoden der transportierten Objekte bleiben dabei erhalten. .. code-block:: sh Dir | Sort-Object Length | Select-Object Name, Length | ConvertTo-Html | Out-File report.htm .\report.htm Bis zuletzt bleiben die Ergebnisse Objekte, von denen relativ leicht bestimmte Eigenschaften (Name, Length) ausgegeben werden können .. topic:: Zitat "What you see here is a true object-oriented pipeline so the results from a command remain rich objects. Only at the end of the pipeline will the results be reduced to text or HTML or whatever you choose for output. Take a look at Sort-Object. It sorts the directory listing by file size. If the pipeline had simply fed plain text into Sort-Object, you would have had to tell Sort-Object just where the file size information was to be found in the raw text. You would also have had to tell Sort-Object to sort this information numerically and not alphabetically. Not so here. All you need to do is tell Sort-Object which object property you want to sort. The object nature tells Sort-Object all it needs to know: where the information you want to sort is found, and whether it is numeric or letters. You only have to tell Sort-Object which object property to use for sorting because PowerShell sends results as rich .NET objects through the pipeline. Sort-Object does all the rest automatically. Simply replace Length with another object property, such as Name or LastWriteTime, to sort according to these criteria. Unlike text, information in an object is clearly structured: this is a crucial PowerShell pipeline advantage." **Aufgabe**: Übersetzen Sie den englischen Text sinngemß. .. only:: html .. sidebar:: Übersetzung SinngemÜ in die deutsche Sprache .. image:: images/notizzettel.png :width: 50px :alt: alternate text :align: left :target: _images/notizzettel.png .. only:: latex .. image:: images/notizzettel.png :width: 1300px .. index:: Out-Default Das Konzept der Pipeline wird auf alle Ausgaben angewendet, auch wenn dies nicht immer explizit zu erkennen ist. Auf alle Ausgaben wid das Out-Default-Cmdlet hinzugefügt, welches die Ausgabe in Textform bewirkt Ein DIR ist damit eigentlich ein DIR | Out-Default. Folgende Cmdlets stehen zur Verfügung. .. image:: images/pipeline_cmdlet_1.png .. image:: images/pipeline_cmdlet_2.png .. image:: images/pipeline_cmdlet_3.png .. image:: images/pipeline_cmdlet_4.png .. image:: images/pipeline_cmdlet_5.png .. index:: Pipeline; Streaming .. index:: Pipeline; Blocking Streaming vs Blocking ===================== Bei der Kombination per Pipeline kommt schnell die Frage auf, wann denn jetzt ein einzelner Befehl tatsächlich umgesetzt wird. Dies hängt vom jeweiligen Modus ab, in dem die Pipeline arbeitet. .. index:: Pipeline; sequentieller Modus *Sequentieller Modus:* In diesem Modus werden die Befehle streng hintereinander ausgeführt, d.h. die Eregbnisse werden erst dann per Pipeline weitergereicht, wenn es komplett berechnet ist. Dieser Modus ist langsam und speicherintensiv, lässt sich aber nicht immer vermeiden, z.B. beim Sort-Object-Cmdlet. So sind im unteren Beispiel die ersten beiden Pipeline sequentiell, während das 3. Beispiel streaming-fähig ist. .. code-block:: sh # Attention: danger! Dir C:\ -recurse | Sort-Object Dir C:\ -recurse | more Dir c:\ -recurse | Out-Host -paging .. index:: Pipeline; streaming Modus *Streaming Modus:* Hier wird jedes einzelne Ergebnis einer Berechnung sofort an den nächsten Befehl weitergereicht .. only:: html .. sidebar:: Tafelbild Streaming vs Blocking .. image:: images/notizzettel.png :width: 50px :alt: alternate text :align: left :target: _images/notizzettel.png .. only:: latex .. image:: images/notizzettel.png :width: 1300px Eigenschaften der Objekte ========================= Um nicht nur die Standard-Eigenschaften der Objekte zu sehen, kann man sich mit Hilfe Format-Cmdlets einen Überblick über die Eigenschaften geben. .. index:: Format-Table, Format-List, Format-Cmdlet .. code-block:: sh Dir | Format-Table * Dir | Format-List * Die Darstellung der Ausgabe kann mit Hilfe von 4 Format-Cmdlets erfolgen: .. code-block:: sh Get-Command -verb format CommandType ----------- Cmdlet Cmdlet Cmdlet Cmdlet Name ---- Format-Custom Format-List Format-Table Format-Wide Definition ---------- Format-Custom [[-Property] ... Ausgabe ======= Die Ausgabe spezieller Eigenschaften erfolgt dann durch Hintereinanderstellen der jeweiligen Namen. Wildcards sind erlaubt. .. image:: images/pipeline_format_table.png .. code-block:: sh Get-Process i* | Format-Table name,pe*64 .. image:: images/pipeline_format_table_2.png Skriptblöcke und künstliche Eigenschaften sind ebenso möglich: Im unteren Beispiel ist $_ jeweils das aktuelle Objekt in der Pipeline. .. code-block:: sh Dir | Format-Table Name, { [int]($_.Length/1KB) } PS C:\temp> Dir | Format-Table Name, { [int]($_.Length/1KB) } Name [int]($_.Length/1KB) ---- ---------------------- FirefoxPortable 0 postkarten 0 Ausgabe.txt 3 autorun.inf 0 index.html 4 index_haas.html 3 ShelExec.exe 60 Zeungnisbemerkung_11FI2_2009 3 Oder man möchte wissen, wie alt die Dateien seit der letzten Veränderung sind. Dies liefert uns die Kombination der folgenden Befehle: .. code-block:: sh New-TimeSpan "01/01/2000" (Get-Date) //Zeitdifferenz zwischen heute und dem 1.1.2000 # gibt uns die Zeitdifferenz zwischen Heute und dem letzten Zugriff des jeweiligen Objektes {(New-TimeSpan $_.LastWriteTime (Get-Date)).Days} # kombiniert alles zu einer schönen Pipeline Dir | Format-Table Name, Length, {(New-TimeSpan $_.LastWriteTime (Get-Date)).Days} -autosize .. image:: images/pipeline_format_table_3.png Ändern der Spaltenüberschriften ------------------------------- Die Spaltenüberschriften könhen geändert werden, wenn auch etwas umständlich Dir | Format-Table Name, @{Label="Größe"; Expression={([int]($_.Length/1KB))}} -AutoSize Dir | Format-Table Name, Length, @{Label="Differenz"; Expression ={(New-TimeSpan $_.LastWriteTime (Get-Date)).Days}} -autosize Dir | Format-Table Name, Length, @{Label="Länge"; Expression ={$_.Length}} -autosize Optimieren der Spaltenbreiten ------------------------------ Wegen der Echtzeitausgabe kann Format-Table nicht wissen, wie breit eine Spalte zu wählen ist, um eine optimale Anzeige aller Werte zu erhalten. Man kann dies durch die Option **-auto** erhalten, verliert aber damit den Vorteil der Echtzeit. .. code-block:: sh column = @{Expression={ [int]($_.Length/1KB) }; Label="KB" } Dir | Format-Table Name, $column -auto Name ---- output.htm output.txt backup.pfx cmdlet.txt KB -- 11 13 2 23 Sortieren und Gruppieren der Pipeline-Ergebnisse ================================================= .. note:: So that you can make good use of Sort-Object and all the other following cmdlets, you must also know which properties are available for the objects traveling through the pipeline. In the last section, you learned how to do that. Send the result of Dir to Format-List * first, then you'll see all properties and you can select one to use for subsequent sorting: Dir | Format-List * .. index:: Sort-Object Sortieren --------- Das Sortierung erfolgt mit Hilfe des Sort-Object-Cmdlets. Falls nichts angegeben wird, sucht sich das Sort-Object-Cmdlet seine eigene Property zum Sortieren. .. code-block:: sh Dir | Sort-Object Eigene Sortierkriterien übergibt man mit der Property-Eigenschaft. .. code-block:: sh Dir | Sort-Object -property Length -descending Dir | Sort-Object Extension, Name Dir | Sort-Object Extension, Name -descending #das geht nicht Dir | Sort-Object Extension, Name -descending, -ascending #wir müssen es an eine hash-table übergeben Dir | Sort-Object @{expression="Length";Descending=$true}, @{expression="Name";Ascending=$true} .. image:: images/pipeline_sort_object_many.jpg .. only:: html .. sidebar:: Tafelbild Sortieren als Blocker .. image:: images/notizzettel.png :width: 50px :alt: alternate text :align: left :target: _images/notizzettel.png .. only:: latex .. image:: images/notizzettel.png :width: 1300px .. index:: Group-Object Gruppieren ---------- Mit Hilfe des Group-Object_Cmdlets können Sie Objekte mit gleichen Eigenschaften nach Ihrer Anzahl gruppieren. Das folgende Beispiel gibt die Anzahl der laufenden und gestoppten Dienste zurück. .. code-block:: sh Get-Service | Group-Object Status .. image:: images/pipeline_group_object.jpg .. code-block:: sh $result = Get-Service | Group-Object Status $result[0].Group Dir | Group-Object Extension Dir | Group-Object Extension | Sort-Object Count -descending Count Name Group ----- ---- ----- 26 {data, docbook, Documents, Dokumente und Ein... 18 .log {start.log, 20100318180017.log, Ve... 9 .txt {ctapi_out_gr.txt, Ergebnis3.txt, ergebnisne... 5 .pdf {Abschlussprüfung Winter 2002 - 2003.pdf, an... 5 .jpg {last.jpg, presse_1.jpg, presse_2.jpg, press... 2 .out {err.out, start.out} 2 .zip {dvd_postkarten_16052010.zip, Stoffverteilun... 2 .tex {start.tex, syntax.tex} 2 .GDB {TEST10.GDB, TEST9.GDB} 1 .hnd {sf.hnd} 1 .ods {schueler.ods} Group-Object kann nicht nur nach Eigenschaften gruppieren, sondern auch nach eigenen Ausdrücken. Das folgende Beispiel gruppiert alle Dateien, in Abhängigkeit, ob sie größer als 100 kByte oder kleiner sind. .. code-block:: sh PS C:\> Dir | Group-Object {$_.Length -gt 100KB} Count Name Group ----- ---- ----- 78 False {cruisecontrol-bin-2.8.3, data, docbook, Doc... 23 True {Abschlussprüfung Winter 2002 - 2003.pdf, dv... Das folgende Beispiel gruppiert nach der Anzahl des Vorkommens des jeweils 1. Buchstabens. .. code-block:: sh PS C:\> Dir | Group-Object {$_.name.SubString(0,1).toUpper()} Count Name Group ----- ---- ----- 3 C {cruisecontrol-bin-2.8.3, config.sys, ctapi_... 10 D {data, docbook, Documents, Dokumente und Ein... 3 I {inetpub, Intel, ihk_pruefung.pdf} 4 M {Miranda IM, music, mymiktex, myPass.kdbx} 10 P {PerfLogs, Program Files, ProgramData, Progr... 1 R {RavenDB-Build-101} 13 S {Sounds, steinam, schueler.ods, sf.hnd...} 8 T {TEMP, totalcmd, test.ps1, TEST10.GDB...} 1 U {Users} 3 W {Windows, WiresharkPortable, wepkeys.txt} 2 . {.emacs, .emacs~} 5 A {Abschlussprüfung Winter 2002 - 2003.pdf, Ak... 3 E {Ergebnis3.txt, ergebnisnew.txt, err.out} 2 H {haas.txt, haas_lanig.txt} 1 K {KOS_09_10.dav} 4 L {last.jpg, LA_ansichten_booklet (2).pdf, LA_... Wie man sieht, ist jede Zeile ein eigener Array mit allen Objekten der jeweiligen Gruppierung. Man könnte dies nutzen, um eine alphabetische Liste aller Objekte auszugeben. .. code-block:: sh Dir | Group-Object {$_.name.SubString(0,1).toUpper()} | ForEach-Object { ($_.Name)*7; "======="; $_.Group} CCCCCCC ======= Verzeichnis: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 06.06.2010 21:22 cruisecontrol-bin-2.8.3 -a--- 10.06.2009 23:42 10 config.sys -a--- 01.04.2010 22:23 0 ctapi_out_gr.txt DDDDDDD ======= d---- 20.07.2010 23:00 data d---- 21.08.2009 22:24 docbook d---- 25.07.2010 20:28 Documents d---- 31.07.2009 22:40 Dokumente und Einstellungen d---- 24.02.2010 08:58 download d---- 20.05.2010 18:09 dvd_postkarten_16052010 -a--- 23.11.2009 21:27 264 dfsd.nsd -a--- 18.12.2009 21:20 7737 dienste.htm -a--- 16.05.2010 20:30 1665 dsd.aup -a--- 10.06.2010 08:30 289840446 dvd_postkarten_16052010.zip IIIIIII ======= d---- 18.08.2009 20:54 inetpub d---- 18.08.2009 09:27 Intel -a--- 02.08.2009 21:35 165025 ihk_pruefung.pdf MMMMMMM .. index:: noelement Wenn man die gruppierten Objekte selbst nicht benötigt, kann man mit Hilfe des **-noelement**-Parameters Speicher sparen. .. code-block:: sh Get-Process | Group-Object -property Company -noelement Count Name ----- ---- 2 Apple Inc. 4 5 1 AVerMedia TECHNOLOGIES... 1 AVerMedia 3 Avira GmbH 32 Microsoft Corporation 2 Firebird Project 1 Google 1 Google Inc. 4 Intel Corporation 1 Irfan Skiljan 2 Sun Microsystems, Inc. 1 Tracker Software Produ... 1 C. Ghisler & Co. 1 http://tortoisesvn.net .. index:: Where-Object, Filter .. index:: Where-Object Filtern ======= Mit Hilfe des Where-Objectes können die Objekte der Pipeline gefiltert werden. .. code-block:: sh PS C:\> Get-Service | Where-Object { $_.Status -eq "Running" } | more Status Name DisplayName ------ ---- ----------- Running AntiVirSchedule... Avira AntiVir Planer Running AntiVirService Avira AntiVir Guard Running AppHostSvc Anwendungshost-Hilfsdienst Running Apple Mobile De... Apple Mobile Device Running AudioEndpointBu... Windows-Audio-Endpunkterstellung Running Audiosrv Windows-Audio Running AVerRemote AVerRemote Running BFE Basisfiltermodul Running BITS Intelligenter Hintergrundübertragungsdienst Running Bonjour Service Dienst "Bonjour" Running Browser Computerbrowser Running CertPropSvc Zertifikatverteilung .. index:: $_ Das Cmdlet erwartet, dass man in geschweiften Klammern einen Powershell-Befehl übergibt. Das jeweils zu untersuchende Objekt kann über die Variable $_ angesprochen werden. Die Eigenschaft Status wird dann auf den Wert Running verglichen. Nur wenn dieses Objekt den entsprechenden Wert hat, wird es in die Pipeline gelassen. Damit entspricht das Where-Objekt im Grunde der Formulierung einer Bedingung, die TRUE ergeben muss. .. code-block:: sh Get-WmiObject Win32_Service | ? {($_.Started -eq $false) -and ($_.StartMode -eq "Auto")} | Format-Table .. image:: images/pipeline_where.jpg Das gleiche Ergebnis hätte man auch ohne Where-Objekt erhalten können, indem man WMI mit den korrekten Fragen füttert. .. code-block:: sh Get-WmiObject -query "select * from win32_Service where Started=false and StartMode='Auto'" | Format-Table .. image:: images/pipeline_wmi_ohne_where.jpg .. index:: Select-Object, first, last, Alias Begrenzen der Anzahl der Ausgabe --------------------------------- Select-Object kann neben der Ausgabe bestimmter Eigenschaften auch die Anzahl der ausgegebenen Datensätze begrenzen .. code-block:: sh # List the five largest files in a directory: Dir | Sort-Object Length -descending | Select-Object -first 5 # List the five longest-running processes: Get-Process | Sort-Object StartTime | Select-Object -last 5 | Format-Table ProcessName, StartTime # Alias shortcuts make the line shorter but also harder to read: gps | sort StartTime -ea SilentlyContinue | select -last 5 | ft ProcessName, StartTime .. index:: Foreach-Object Foreach-Objekt ============== Anstelle auf die Ergebnisse einer Pipeline zu warten, kann mit Hilfe des Foreach-Object-Cmdlets sofort auf jedes einzelne Objekt zugegriffen werden. Foreach-Object erwartet in geschweiften Klammern eine Anweisung, was es mit dem jeweiligen Objekt anstellen soll. .. code-block::sh Get-Service | ForEach-Object { "The service {0} is called '{1}': {2}" -f $_.Name, $_.DisplayName, $_.Status } .. index:: Filter Foreach-Object kann wie das Where-Object als Filter verwendet werden. Dazu muss nur in der geschweiften Klammer eine Bedingung formuliert werden. Das Where-Object hat man eigentlich nur aus Beguemlichkeit geschaffen. Die folgenden Befehle haben alle das gleiche Ergebnis. .. code-block:: sh Get-Service | Where-Object { $_.Status -eq "Running" } Get-Service | ? { $_.Status -eq "Running" } Get-Service | ForEach-Object { if ($_.Status -eq "Running") { $_ } } Get-Service | % { if ($_.Status -eq "Running") { $_ } } .. note:: ForEach-Object actually executes three script blocks, not just one. If you specify only one script block in braces after ForEach-Object, it will be executed once for every pipeline object. If you specify two script blocks, the first will be executed once and before the first pipeline object. If you specify three script blocks, the last will be executed once after the last pipeline object. The following will help you carry out initialization and tidying tasks or simply output initial and ending messages: .. code-block:: sh Get-Service | ForEach-Object {"Running services:"}{ if ($_.Status -eq "Running") { $_ } }{"Done."} The three script blocks of ForEach-Object actually correspond to the three script blocks begin, process, and end, which you'll examine in more detail later .. only:: html .. sidebar:: Tafelbild Übersetzen Sie den englischen Text .. image:: images/notizzettel.png :width: 50px :alt: alternate text :align: left :target: _images/notizzettel.png .. only:: latex .. image:: images/notizzettel.png :width: 1300px Zwischenergebnisse ================== .. index:: Tee-Object Während einer Pipeline-Operation können mit Hilfe des Tee-Objektes die Zustände von Pipeline-Operationen in Variablen zwischengespeichert werden. .. code-block:: sh Get-Process | Tee-Object -variable a1 | Select-Object Name, Description ` | Tee-Object -variable a2 | Sort-Object Name ` $a1 $a2 Ausgabe von Pipeline-Ergebnissen ================================ .. TODO:: Mehr zu Export-Cmdlets schreiben (export-csv, export-html, ...) Funktionen und Pipeline ======================= .. TODO:: Noch mehr schreiben (bei Funktionen schauen) Pipeline oder Schleife ====================== Häufig ist ein Problem sowohl mit Hilfe der Pipeline als auch mit Hilfe der "normalen" strukturierten Programmierung möglich. Je nach Szenario kann es allerdings zu erheblichen Geschwindigkeitsunterschieden kommen. Folgendes Beispiel verdeutlicht den Zusammenhang. .. code-block:: sh #eine strukturierte Herangehensweise an das Problem #Schleife mit if #3 Minuten, 18 sec #$zeit = Get-Date #$result = Get-Content $env:windir\Windowsupdate.log #foreach($zeile in $result) #{ # if($zeile.Contains("WARNING")) # { # $line = $zeile.Split("`t") # Write-Host ($line[0] + " " + $line[1]) # #Add-Content -Path "C:\ergebnisnew.txt" -value $zeile; # } #} #$diff = $zeit - (Get-Date) #Write-Host $diff #Das gleiche nun mit Pipes #dauert 5 Min, 48 sec !!! #$zeit = Get-Date #Get-Content $Env:windir\WindowsUpdate.log | Select-String "WARNING" | Add-Content "C:\Ergebnis3.txt" #$diff = $zeit - (Get-Date) #auch mit Pipes kann es schneller gehen #Write-Host $diff $zeit = Get-Date Get-Content $Env:windir\WindowsUpdate.log -readCount 1000 | Select-String "WARNING" | Add-Content "C:\Ergebnis3.txt" $diff = $zeit - (Get-Date) Write-Host $diff ` Pipeline/Filter und Funktionen ============================== Funktionen können die Ergebnisse der Pipeline weiterverarbeiten. Es stellt sich lediglich die Frage, ob dies im langsamen *sequentiellen* oder schnelleren *streaming*-Modus vonstatten geht. Sequentieller Modus -------------------- Im einfachsten Falle unterstützt eine Funktion nicht wirklich die Pipeline. Die Ergebnisse der Pipeline stehen in der automatischen Variable **$input** zur Verfügung. Im einfachsten Falle gibt die Funktion einfach die Inhalte von $input aus. .. code-block:: sh Function output { $input } # The function, when invoked alone, # will return nothing because no pipeline # results are available: output # If you create an array in the pipeline, # the function will output the array: 1,2,3 | output 1 2 3 # The function is completely indifferent to # which type of data is in the pipeline: Dir | output Die Funktion soll nun aber abgeändert werden; alle Dateien mit der Endung .exe sollen in roter Farbe ausgegeben werden. .. code-block:: sh function MarkEXE { # Note old foreground color $oldcolor = $host.ui.rawui.ForegroundColor # Inspect each pipeline element separately in a loop Foreach ($element in $input) { # If the name ends in ".exe", change the foreground color to red: If ($element.name.toLower().endsWith(".exe")) { $host.ui.Rawui.ForegroundColor = "red" } Else { # Otherwise, use the normal foreground color: $host.ui.Rawui.ForegroundColor = $oldcolor } # Output element $element } # Finally, restore the old foreground color: $host.ui.Rawui.ForegroundColor = $oldcolor } Measure-Command {Dir "c:\program files" -recurse | MarkEXE } PS C:\Windows\system32> Measure-Command {Dir "c:\program files" ` -recurse | MarkEXE } ` Days : 0 Hours : 0 Minutes : 0 Seconds : 0 Milliseconds : 706 .. Die Ausführung des Skripts dauert 706 msec. Filter ------ Ersetzt man aber das Schlüsselwort **Function** durch das Wort **Filter**, dann ist die Ausgabe ca. um den Faktor 3 schneller. .. code-block:: sh PS C:\Windows\system32> Measure-Command {Dir "c:\program files" ` -recurse | MarkEXEFilter } ` Days : 0 Hours : 0 Minutes : 0 Seconds : 0 Milliseconds : 189 .. Da die $input-Variable für Filter immer nur aus einem Wert besteht, macht ihr Einsatz innerhalb der Schleife wenig Sinn. Man kann Sie besser durch die Variable $_ ersetzen. .. code-block:: sh Filter MarkEXEFilter2 { # Note old foreground color $oldcolor = $host.ui.rawui.ForegroundColor # The current pipeline element is in $_ # If the name ends in ".exe", change # the foreground color to red: If ($_.name.toLower().endsWith(".exe")) { $host.ui.Rawui.ForegroundColor = "red" } Else { # Otherwise, use the normal foreground color: $host.ui.Rawui.ForegroundColor = $oldcolor } # Output element $_ # Finally, restore the old foreground color: $host.ui.Rawui.ForegroundColor = $oldcolor } PS C:\Windows\system32> Measure-Command {Dir "c:\program files" ` -recurse | MarkEXEFilter2 } ` Days : 0 Hours : 0 Minutes : 0 Seconds : 1 Milliseconds : 77 .. Generische Filter ----------------- Filter sind beim Einsatz von Pipelines den Funktionen vorzuziehen, weil Sie die Ergebnisse der Pipeline sofort verarbeiten können. Nachteilig kann sich aber auswirken, dass alle Codeblöcke eines Filters immer wieder aufgerufen werden. In unserem Beispiel wird immer die alte Vordergrundfarbe gespeichert und nach dem Durchlauf wieder zurückgesetzt. Dies ist zeit- und ressourcenintensiv. Das Verhalten einer Funktion kann aber an diese Situation agepasst werden, indem man innerhalb einer Funktion spezielle Bereiche definiert. - begin: (Initialisierung: Wird einmal beim Beginn aufgerufen) - process: - end: Aufräumen; wird einmal am Ende aufgerufen Ein Filter ist für die Powershell nichts anderes als eine Funktion mit einem einzigen **process**-Block. Die optimale Codierung des obigen Problems lagert deswegen das Speichern und Zurücksetzen der Farbein in den begin- bzw. end-Block aus .. code-Block:: sh Function MarkEXE { begin { # Note old foreground color $oldcolor = $host.ui.rawui.ForegroundColor } process { If ($_.name.toLower().endsWith(".exe")) { $host.ui.Rawui.ForegroundColor = "red" } Else { $host.ui.Rawui.ForegroundColor = $oldcolor } # Output element $_ } end { # Finally, restore the old foreground color: $host.ui.Rawui.ForegroundColor = $oldcolor } } .. note:: Das nächste Beispiel zeigt, dass ein Filter in Wirklichkeit eine normale Funktion mit einem process-Block ist. .. code-block:: sh filter Test { "Output: " + $_ } Let's look now at the definition of the filter: $function:Test process { "Output: " + $_ } PowerShell hat die Filter-Anweisung in eine normale Funktion umgewandelt und den Code in einen process-Block gesetzt. Zusammenfassung =============== PowerShell uses a pipeline for all command entries, which feeds the results of the preceding command directly into the subsequent command. The pipeline is active even when you enter only a single command because PowerShell always automatically adds the Out-Default cmdlet at the pipeline's end so that it always results in a two-member instruction chain. Single command results are passed as objects. The cmdlets shown in Table 5.1 can filter, sort, compare, measure, expand, and restrict pipeline elements. All cmdlets accomplish this on the basis of object properties. In the process, the pipeline distinguishes between sequential and streaming modes. In streaming mode, command results are each collected, and then passed in mass onto the next command. Which mode you use depends solely on the pipeline commands used. Output cmdlets dispose of output. If you specify none, PowerShell automatically uses Out-Host to output the results in the console. However, you could just as well send results to a file or printer. All output cmdlets convert objects into readable text while formatting cmdlets are responsible for conversion. In addition to traditional output cmdlets, export cmdlets store objects either as comma-separated lists that can be opened in Excel or serialized in an XML format. Serialized objects can be comfortably converted back into objects at a later time. Because when exporting, in contrast to outputting, only plain object properties, without cosmetic formatting, are stored so that no formatting cmdlets are used. Links ===== http://thepowershellguy.com/blogs/posh/archive/2007/01/21/powershell-gui-scripblock-monitor-script.aspx .. note:: Als Beispiel für begin-process-end sowie pipeline kann man im nächsten Jahr eine Datenbankverbindung nehmen. Die Ergebnisse des dir-Befehls sollen in eine Datenbank geschrieben werden. begin --- öffnet die Verbindung process -- führt die insert-Statements aus end -- schließt die Datenbankverbindung nach dem letzten insert a la : Dir -recurse | insertFileInDatabase