Archiv für den Monat: Februar 2017

Zweites Treffen der PowerShell User Group Stuttgart am 23.02.17

Am 23.02.17 fand das zweite Treffen der PowerShell User Group Stuttgart statt. Der Gastgeber war dieses Mal die Firma Reddoxx (aka Die Netzwerker) in Kirchheim unter Tek (es ist interesssant, dass es von Esslingen aus mit 32km fast genauso weit nach Kirchheim Tek ist wie nach Stuttgart Vaihingen, nur die Fahrzeit kann „ein wenig“ varriieren, wenn auf der A8 Richtung München mal wieder Stau ist).

Es war wieder ein netter und abwechslungsreicher Abend angefüllt mit vielen kleinen und größeren Details rund um die PowerShell. Das Motto des Abends war „Script Review“ oder „Bring your own Script“ (BYOS). Die Idee war, dass jeder seine PowerShell-Skripte hätte mitbringen können, die dann unter fachkundiger Begutachtung aller Anwesenden auf Schwachstellen und mögliche Verbesserungen hätten abgeklopft werden sollen.

Das Fazit des Abends war, dass jeder der Annwesenden wieder einiges über die PowerShell dazu gelernt hat, mich eingeschlossen. So muss ich zugeben, dass ich bislang nicht wusste, dass sich auch Functions „dot sourced“ aufrufen lassen. In diesem Fall werden die lokalen Variablen der Functions in die Ebene des Aufrufers übernommen und stehen dort nach Beendigung der Function noch zur Verfügung. Mit anderen Worten, die lokalen Variablen einer Function werden durch den dotsoured-Aufruf zu Skriptvariablen. Mir fällt zwar nach wie vor kein Anwendungsfall dafür ein, interessant ist diese Technik aber in jedem Fall.

Der Termin für das dritte Treffen steht bereits fest: Am 15. März 2017, dieses Mal wieder in den Räumen von Microsoft in Stuttgart Vaihingen. Alle Infos gibt es hier:

https://www.meetup.com/de-DE/German-PowerShell-Usergroup/events/237720913/

Eine Anmeldung über Meetup ist erforderlich. Das setzt eine Registrierung bei Meetup voraus, ist aber in 2-3 Minuten erledigt.

Beim Script-Review herrschte absolute Hochspannung

Script-Review in Action

Ein weiteres Stimmungsbild vom zweiten Treffen der PowwerShell User Group Stuttgart in Kircheim Tek

Famous „Einzeiler“ in PowerShell

Es muss nicht immer gleich ein Skript sein, auch mit einem Einzeiler lässt sich bereits einiges bewerkstelligen. Auf Stackoverflow.com hat vor einigen Zeit eine Frage eine Vielzahl interessanter Einzeiler hervorgebracht:

http://stackoverflow.com/questions/615287/useful-powershell-one-liners?rq=1

Vergleichbar mit den „famous quotes“ gibt es natürlich auch ein paar „famous onliner“ in PowerShell. Hier ein paar Kostproben.

1) Auflisten aller Dateien, die ich heute geändert habe

2) Bei Visual Studio-Menüs die Großschreibung deaktivieren (11.0 steht für VS 2012)

3) Dateien auf den Desktop kopieren

Originell sind Beiträge wie „exit“ oder „gps programThatIsAnnoyingMe | kill“.

Ich habe natürlich selber auch jede Menge Einzeiler, die ich an dieser Stelle in naher Zukunft zusammenstellen werde (alleine in jeder Schulung fallen ein paar dieser Einzeiler an, die dann wieder in Vergessenheit geraten).

Tipp: Die Registry gekonnt durchsuchen

Der Umstand, dass die Registry-Hives wie HKey_Local_Machine als Laufwerk angesprochen werden, ist nur auf den ersten Blick eine Vereinfachung. Das wird spätestens dann deutlich, wenn man die Registry nach Einträgen (Names) eines Schlüssels und deren Werten (Values) durchsuchen möchte. Zwar zeigt ein dir hklm:\Software\Microsoft\Windows\CurrentVersion\Uninstall auch die Einträge der Schlüssel und ihre Werte an, liefert diese aber nicht zurück.

Der folgende Befehl funktioniert daher nicht.

Es gibt bei den zurückgegebenen Objekten ganz einfach keine Eigenschaft DisplayName. Bevor man jetzt allzu viel Zeit mit einer Suche nach einer Lösung verlierrt, was es gibt sind Methoden-Members wie GetValueNames und GetValue.

Der folgende Befehl gibt für alle installierten Anwendungen Anzeigename und Versionsnummer aus.

Weiß man nicht, welcher Schlüssel einen bestimmten Eintrag (Name) besitzen könnte, kommt die Methode GetValueNames in Frage.

Der folgende Befehl gibt alle Schlüssel aus, in denen eines Eintrag „ExecutionPolicy<" gibt.

Es stellt sich heraus, dass die Einstellung für die Ausführungsrichtlinie für den gesamten Computer unter HKEY_LOCAL_MACHINE\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell aufgehängt ist.

Der folgende Aufruf von Powershell.exe ändert die Einstellung z.B. auf „Restricted“.

Tipp: Zu welchem Namespace gehört ein Parametertyp?

Sobald man sich mit der PowerShell ein wenig besser auskennt (das kann unter Umständen ein paar Jahre dauern;) achtet man mehr auf die Feinheiten. Dazu gehört z.B. die Frage auf welchem (Daten-) Typ bestimmte Parameter basieren. Nehmen wir als Beispiel den Parameter ExecutionPolicy von Set-ExecutionPolicy. Ist sein Wert ein String oder eine Zahl? Weder noch, die Syntaxbeschreibung verrät, dass der Datentyp, große Überraschung, ExecutionPolicy ist. Da für den Parameter lediglich bestimmte Werte in Frage kommen, steht der Datentyp für eine Konstantenliste, eine Enum. Die Konstantenliste umfasst eine Reihe von Zahlenwerten, die durch Namen repräsentiert werden.

Es ist typisch für die PowerShell, dass eine automatische Typenkonvertierung durchgeführt wird. Übergebe ich für den Parameter z.B. „Unrestricted“, also einen String, wird dadurch automatisch die gleichnamige Konstante ausgewählt.

Was sicher nicht jeder weiß, es ist grundsätzlich sehr einfach die geladenen Assemblies nach einem bestimmten Typ zu durchsuchen, um sich z.B. den Namespace ausgeben zu lassen. Kennt man den Namespace, erfährt man alles über den Typ des Enum und kann sich z.B. alle Felder ausgeben lassen.

Der folgende Befehl führt eine Suche unter allen geladenen Typen durch.

Es stellt sich heraus, dass die vollständige Typenbezeichnung Microsoft.PowerShell.ExecutionPolicy ist.

Ein [Microsoft.PowerShell.ExecutionPolicy].GetFields().Name gibt z.B. die Namen der einzelnen Konstanten aus.

Da wir gerade dabei sind, wie erhalte ich den Zahlenwert einer Konstanten wie z.B. RemoteSigned? Ganz einfach per Typenkonvertierung z.B. in einen Int.

Also, keine „Angst“ vor speziellen PowerShell-Typen, sie lassen sich wie gezeigt sehr einfach in den geladenen Assemblies lokalisieren.

Endlich: Farbige Ausgaben (aber nur unter Windows 10 und Windows Server 2016)

Wenn die PowerShell in einem Punkt im Vergleich zu den Linux-Shells etwas blass aussieht, dann aufgrund der nüchternen Schwarz-Weiß-Optik. Es ist einfach nichts bunt. Klar, per Write-Host lässt sich jede Ausgabe farbig machen, aber wir wissen ja, dass wir Write-Host nicht verwenden sollen, da es die Ausgabe direkt in die Konsole schreibt – es ist in diesem Fall eine reine Textausgabe. Weiterverarbeitung nur sehr eingeschränkt möglich.

Seit Windows 10 und Windows Server 2016 und WMF 5.1 gibt es eine endlich eine Lösung. Sie besteht darin, dass das Konsolenfenster VT100-Escape-Sequenzen erkennt und entsprechend umsetzen kann. Unter anderem gibt es Esc-Seqenzen für eine farbige Ausgabe. Jetzt muss man nur noch eine Typenformatierungsdatei für den auszugebenden Typ anlegen, dort die Esc-Sequenzen einbauen und schon wird die Eigenschaft in einer anderen Farbe ausgegeben.

Hier ist ein „kleines“ Beispiel, das die Formatierung für Process-Objekte ersetzt und bewirkt, dass ein Get-Process mit Name und WS(MB) nur noch zwei Spalten anzeigt. Die Ausgabe in der Spalte WS(MB) wird immer dann rot angezeigt, wenn der Wert größer 50MB ist – denkt bitte daran, dass das nur ab Windows Server 2016 und Windows 10 ab Anniversary Update und WMF 5.1 funktioniert.

Wer viel Zeit hat, kann natürlich weitere Spalten definieren bzw. eine benannte View anlegen, die bei Format-Table per View-Parameter ausgewählt wird. Möglich ist, wie immer, vieles. Man muss nur die Zeit haben und experimentierfreudig sein…

Farbige Ausgaben dank VT100-Unterstützung in der modernen Konsole

Praktisch: Dateien kopieren mit Fortschrittsanzeige

Das „Problem“ beim Kopieren von mehreren Dateien ist, dass die Anzahl der zu kopierenden Dateien am Anfang in der Regel nicht bekannt ist. Möchte man Dateien mit Hilfe einer Function pipelinebasierend kopieren, gibt es in der Regel keine Möglichkeit an die Anzahl der Dateien, die der Function übergeben werden, heranzukommen. Der „Trick“ mit $Input.Count funktioniert ab der Version 3.0 nicht in einer Pipeline-Function.

Eine einfache Lösung besteht darin, die zu kopierenden Dateien im Process-Block zu sammeln und die Dateien erst im End-Block zu kopieren. In dieser Aufteilung werden die Dateien im Process-Block lediglich gezählt, um dann im End-Block im Rahmen einer ForEach-Wiederholung kopiert zu werden.

Das folgende Beispiel veranschaulicht das Prinzip.

Aufgerufen werden kann die Function wie folgt: