Archiv für den Monat: Oktober 2020

Praxistipp: Wurden alle Zip-Dateien ausgepackt?

Große Laufwerksdateien können auch als eine Sammlung von kleineren Zip-Dateien zur Verfügung gestellt werden, die alle heruntergeladen, extrahiert und mit einem Tool wie 7Zip zu einer großen Datei oder einer Verzeichnisstruktur zusammengesetzt werden. Da nach dem Extrahieren mehrere Dutzend Zip-Dateien mit einer durchgehenden Nummerierung (z.B. Datei001, Datei002, Datei004 usw.) vorliegen stellt sich die Frage, ob alle Dateien vollständig sind.

Als PowerShell-Einsteiger würde man vielleicht versuchen, ein kleines Skript zu schreiben, das alle Dateien einliest, irgendwie die Nummern aus dem Dateinamen extrahiert und in einem weiteren Schritt z.B. im Rahmen einer Schleife von 1 bis n prüft, ob jede Zahl in der Liste der Dateinamen vorkommt.

Es geht natürlich auch etwas einfacher. Dank dem praktischen Group-Object-Command lässt sich alles in einer Befehlszeile zusammenfassen. Voraussetzung ist, dass sich alle Zip-Dateien im aktuellen Verzeichnis befinden


dir | select-object -expand Name | select-string "\.(\d+)$" | select-object @{n="Nr";e={$_.Matches[0].Groups[1].Value}} | Group-Object Nr | Where Count -eq 1

PowerShell Conference Europe 2020 – viele spannende Themen

Die PowerShell Conference Europe 2020 hat zwar corona-bedingt nur als reine Online-Konferenz stattgefunden, beim Überfliegen der im Januar veröffentlichten Themen im PowerShell Magazine wird schnell deutlich, dass auch offline eine sehr gute Konferenz geworden wäre:

Auch wenn ich den letzten ca. 15 Jahren bereits einiges mit der PowerShell gemacht habe, es ist immer wieder faszinierend zu sehen, wie kreativ viele Menschen sie einsetzen und vor allem, welche Erweiterungen sie sich einfallen lassen (u.a. Import-Excel oder das Universal Dashboard, um nur einmal zwei der Erweiterungen zu nennen, die sich jeder einmal anschauen sollte).

Ich bin sicher, dass die meisten der ausgefallenen Vorträge 2021 nachgeholt werden. Gleichzeitig ist mein Eindruck, dass die Themen, so spannend sie auch sind, für die meisten Anwender der PowerShell „over the top“, also sehr weit weg sind. Wer den Anschluss nicht ganz verlieren möchte, muss sich lediglich ein wenig ausführlicher und eventuell auch systematischer mit den PowerShell-Grundlagen beschäftigen (einfach einmal per Get-Help about_* alle About-Themen auflisten und sich jeden Tag ein Thema vornehmen) und vielleicht auch in seiner Arbeitsumgebung (sprich Firma) einen Rahmen schaffen, in dem PowerShell-Skripte sinnvoll und langfristig eingesetzt werden.

Tipp des Tages: Einzelaktionen ausführen mit Invoke-Command statt ForEach-Object

Eine der größten Hürden, die PowerShell-Einsteiger (bildlich gesprochen) überwinden müssen ist zu verstehen, wie auf eine Get-Abfrage eine individuell festgelegte Aktion folgen kann.

Beispiel: Wenn ein bestimmter Dienst nicht ausführt, soll eine Mail verschickt und ein Eintrag in einer Log-Datei geschrieben werden. Das Beispiel wirkt vielleicht ein wenig konstruiert. Es geht im Grunde darum, dass auf eine Get-Abfrage eine Aktion folgen soll, die sich nicht nur ein einzelnes Cmdlet abbilden lässt.

Die Lösung besteht normalerweise im Aufruf des ForEach-Object-Cmdlets, in dessen Process-Scriptblock alle Aktionen aneinandergereiht werden:

Get-Service -Name WinRM| Where-Object Status -ne "Running" | ForEach-Object {
"Aktion1"
"Aktion2"
}

Was mir an der Umsetzung nicht ganz so gut gefällt ist der Umstand, dass ForEach-Object auch dann verwendet wird, wenn nur eine Aktion ausgeführt werden soll.

Eine Alternative ist das Invoke-Command-Cmdlet. Auch wenn es in erster Linie für PowerShell-Remoting verwendet wird, kann es natürlich auch für lokale Ausführungen verwendet werden. Im einfachsten Fall wie folgt.

Get-Service -Name WinRM | Where-Object Status -ne "Running" | Invoke-Command {
"Aktion1"
"Aktion2"
}

Ganz optimal ist diese Variante sicher auch nicht. Vielleicht sollte es einfach nur mit „Invoke-Scriptblock“ einen weiteren Alias für ForEach-Object geben:

Set-Alias -Name Invoke-Scriptblock -Value ForEach-Object

Get-Service -Name WinRM | Where-Object Status -ne "Running" | Invoke-Scriptblock {
"Aktion1"
"Aktion2"
}