Infosite von Joe Brandes
Eine Website von Trainer Joe Brandes. Infos zu IT-Seminaren von A bis Z.
Das klassische PCS Zertifikat
Von der Hardware und Netzwerktechnik bis zu den den Betriebssystemen Windows, Windows Server und Linux
Ich biete diese Module an!
Zertifikat CMSOD
Module Basiszertifikat
Module Specialist
Ready for Tech Deep Dives...
Bitte gerne ihre gewünschten Seminarinhalte anfragen!
An der VHS Braunschweig findet vom 16. bis 20. Dezember 2024 ein Bildungsurlaub zum Thema "PowerShell - die Befehlszeile für den Windows-Profi" statt. In einem praxisorientiertem Seminar und mit den aktuellen Betriebssystemen und Anwendungen aus dem Hause Microsoft werden wir uns die moderne und zukunftsorientierte "Konsole - Kommandozeile - Shell" von Microsoft für nahezu alle Betriebssysteme erarbeiten.
Hier die Rahmendaten unseres Seminars:
Ort: VHS Braunschweig, Heydenstraße 2, Raum 2.11Termine: Mo., 16.12. bis Fr., 20.12.2024; jeweils 08.30 - 16.00 UhrDownloads: OneDrive (Daten Trainer Joe Brandes für verschiedene Seminare)
Ich werde unsere Seminarthemen an dieser Stelle ausführlich begleiten und die Infos rund um die PowerShell nachhaltig verfügbar machen. Ihr Trainer Joe Brandes
Intro:
Den Trainees / Teilnehmern (TN) des Seminars stehen aktuelle Windows 11 (Education) Systeme zur Verfügung.
Die Basisinstallationen werden als Wechsel-SSD für die TN zu Beginn des Seminars verteilt. Die notwendigen Zugangsdaten (Benutzername + Passwort) werden ebenfalls koordiniert.
Bereitstellung ausführlicher Trainingsmaterialien:
Diesen Begriff hört man in meinen Seminaren häufiger ;-). Gemeint ist hier: Das grundsätzliche Verständnis der fraglichen IT-Techniken. Am Besten gleich so, dass man auch nach einer Zeit ohne Beschäftigung mit diesen Techniken sehr schnell wieder in Fahrt kommt.
Unter einem roten Faden versteht man ein Grundmotiv, einen leitenden Gedanken, einen Weg oder auch eine Richtlinie. „Etwas zieht sich wie ein roter Faden durch etwas“ bedeutet beispielsweise, dass man darin eine durchgehende Struktur oder ein Ziel erkennen kann. Quelle: Wikipedia - Roter Faden
Unter einem roten Faden versteht man ein Grundmotiv, einen leitenden Gedanken, einen Weg oder auch eine Richtlinie. „Etwas zieht sich wie ein roter Faden durch etwas“ bedeutet beispielsweise, dass man darin eine durchgehende Struktur oder ein Ziel erkennen kann.
Quelle: Wikipedia - Roter Faden
Ich zitiere an dieser Stelle einmal aus einem Exchange-Fachbuch von T. Stensitzki um außerdem noch die besondere Bedeutung der PowerShell für die Windows-Administrationen herauszustellen:
Wenn Sie an dieser Stelle des Buches angekommen sind und zum ersten Mal etwas über PowerShell lesen, so kann ich Ihnen nur einen Rat geben: Lernen Sie PowerShell! Die aktuellen Versionen von Exchange Server und alle wie auch immer gearteten Clouddienste von Microsoft erfordern die Administration per PowerShell. Es gibt keine Alternative! Quelle: T. Stensitzki - Exchange Server Fachbuch
Wenn Sie an dieser Stelle des Buches angekommen sind und zum ersten Mal etwas über PowerShell lesen, so kann ich Ihnen nur einen Rat geben: Lernen Sie PowerShell! Die aktuellen Versionen von Exchange Server und alle wie auch immer gearteten Clouddienste von Microsoft erfordern die Administration per PowerShell. Es gibt keine Alternative!
Quelle: T. Stensitzki - Exchange Server Fachbuch
Und diesem Rat will ich mich gerne aus vollem PowerShell-Herzen anschließen ;-)
Die Ausarbeitungen im Rahmen meiner PowerShell-Seminare und Interessen finden Sie als RestructuredText Dokumente unter powershell.joe-brandes.de.
Mal sehen wo die Reise mit dieser Unterlage noch hingeht...
Topics:
Und los geht es mit dem PowerShell Thema...
Wir setzen als Betriebssyteme Windows 11 (Pro bzw Education) ein. Später sollten dann auch Techniken der PowerShell in einer Windows Server 2016/2019/2022 (2025) Active Directory Domänenumgebung (AD mit entsprechenden PowerShell AD-Modulen zum Einsatz kommen.
[Alt / Pre-Win10] Es waren früher PowerShell "Downloads" für Pre-Win-10 notwendig: PowerShell Version 5.1 oder eigentlich: Microsoft Windows Management Framework 5.1 (Link zum MS Download)
Microsoft entwickelt - sehr aktiv und als OpenSource auf Github - auch eine plattformunabhängige Version PowerShell 7.x (Vorversion Core 6.x) für diverse Betriebssysteme
Quellen:
Der Zusatz Core wird von Microsoft (aktuell) bei Version 7 weggelassen - die Version heißt einfach und schlicht PowerShell!
Übersicht zu PowerShell-Versionen und deren Betriebssystemverfügbarkeiten: Wikipedia - PowerShell
Deutsche Einstiegsseite zum Thema Microsoft PowerShell: Microsoft Dokumentation / Skriptcenter
Installationsverzeichnis: C:\Windows\System32\WindowsPowerShell\v1.0 Anm.: ja immer noch Version 1.0 ;-) im Pfad
C:\Windows\System32\WindowsPowerShell\v1.0
Siehe vordefinierte Variable $PSHome:
# PS-Version anzeigen lassen echo $PSVersionTable # Host - in Console (und ISE) testen $host.Version # Installationsverzeichnis Write-Host $PSHome
Hier ist die 64-Bit-Variante auf 64-Bit-OS zu finden (Tipp GUI: Systemeigenschaften mit Win + Pause).
Die 32-Bit-Variante im SysWoW64-Ordner (!): C:\Windows\SysWOW64\WindowsPowerShell\v1.0 Warum ist das wichtig? Zum Beispiel beim Zugriff auf eine 32-Bit MS Access Datenbank!
C:\Windows\SysWOW64\WindowsPowerShell\v1.0
Anm.: Die PowerShell (PS) kennt keine Groß-/Kleinschreibung Unterscheidung (non case-sensitive).
Mit dem folgenden Diagramm (SmartArt) möchte ich dem schon erwähnten Faden noch mehr Struktur geben. Das Diagramm bildet die Erkenntnisse zu PowerShell Struktur und Nutzungen ab.Insbesondere in der Rubrik "Cmdlets" muss bei der Nutzung der PowerShell klar werden, dass wir keinesfalls Tausende von Aufrufen (Commands) der PowerShell kennen müssen. Wir benötigen ein paar Grundkommandos und von da ergeben sich die weiteren Anwendungen und Aufrufe.Für die Aufteilung der Schwerpunkte lassen sich Inhalte und Kenntnisse zur PowerShell auch in einzelne Seminare aufsplitten.
Projektname "Monad" (8. August 2002 - Das Monad Manifest) - der Versuch das "Beste aus allen Welten" zu kombinieren und zu verbinden!
In PowerShell Integrierte Techniken (siehe Planungen bei Urprojekt Monad):
Die Idee: alle möglichen Techniken in einer "Umgebung" zu vereinen!
Die PowerShell verarbeitet Aufrufe nach einem Ranking / einer Reihenfolge.
Hinweis: durch diese Reihenfolge "überschreibt" ein Alias notepad die Aufrufe der Applikationen mit gleichem Namen!
notepad
Wir nutzen den Tabulator zur Codevervollständigung (auch Umschalten + TAB rückwärts - inkl. Wildcards):
Get-?e* TABGet-Command Get-* Get-Command [gs]et-*Get-Command *-Service Get-Command –Noun Service Get-Command *wmi*
Beispiel mit mehr Tiefe als Vorbereitung auf Pipelining und Filterungen:
Get-Command | Where-Object { $_.name -like "*cim*" -or $_.name -like "*wmi*" } Get-Command ps # AliasGet-Command notepad.exe # ToolGet-Command C: # Function
Anzahl von Cmdlets und Funktionen (so seit PS 2.0)[Anm.: Status 2024 Windows 11 System ca. 2300 Commands!]
Get-Command | Group-Object CommandType# Cmdlets und Funktionen exportieren:Get-Command | Format-Table name -HideTableHeaders | Out-File E:\_temp\pscommands.txt
Hilfe zu PS-Befehlen und den Techniken für das spätere Skripting:
Get-Help about_for Get-Help about_foreach Get-Help about (alle verfügbaren Hilfen)
Empfehlung: auch einfach online suchen mit "PowerShell about_for, ...Online-Hilfe-Portal zur PowerShell (Technet - Skripterstellung mit Windows PowerShell)
Hilfe aktualisieren: [Hinweis ab 202x: die Installationen der lokalen Hilfen eigentlich nicht mehr nötig/gewünscht]
Update-Help –UICulture En-US -force# Beachten: Admin-PowerShell nötig! # Anm.: Autor Weltner empfiehlt En-US Schalter! Ich lasse Schalter weg!;-) Get-Help Get-Command# mit Parametern auch Get-Help Get-Command -Detailed # -Full, -Examples, -Online, -ShowWindow Get-Help Get-Process -parameter "*"
Hilfe aktualisieren mit Update-Help Commandlet - Beachten: Administrator-PowerShell nötig!
Update-Help
Show-Command für mehr GUI: (siehe später auch -ShowWindow Parameter)[das "catched" dann auch die "Fenster-User" 😜 ]
Show-Command Get-Process
Grafische Oberfläche mit Show-Command seit PS 3.0: Show-Command Get-Process
Websites: Skripting mit der PowerShell - Windows PowerShell for Server
... ein PowerShell-Modul für das Verbessern der PowerShell Konsole
Seit PS 5.0 hat man außerdem mit PowerShellGet, ein Modul, das die Fähigkeiten von NuGet (einem Paketmanager) bereitstellt.
In älteren PowerShells: falls man kein Modul PSReadline vorfindet, dann bitte Cmdlet Install-Modul zum Installieren nutzen: (in einer Administrator-Shell)Install-Modul -Name PSReadline
Install-Modul -Name PSReadline
Wichtig: Abfragen nach Installation von Paketmanagement-Tool und Vertrauenswürdigkeit des Paketrepositories mit "Y" bestätigen! Zu diesen Modul-Techniken im Seminar später mehr!
Verbesserungen in der PowerShell-Konsole durch PSReadline: (Beispiel-Link)
Bitte Tasten(-kombinationen) nutzen für effiziente PowerShell-Nutzung:
Tipp: Spalten markieren mit gehaltener Alt-Taste vor dem Markieren mit der Maus.
Die PowerShell hat eine eigene History-Umgebung und stellt entsprechende Cmdlets zur Nutzung.Diese History ist aber auf die laufende Session begschränkt und müsste von uns manuell "gerettet und genutzt werden.
Am Besten man nutzt die History-Technik von Modul PSReadline
# PSReadline(Get-PSReadlineOption).HistorySavePath$a = (Get-PSReadlineOption).HistorySavePathnotepad.exe $a # oder auch mit dem ISEise $a
Es ist also mit der History.txt-Datei von PSReadline ein kompletter Fundus unserer Aufrufe am Ende der Seminarwoche automatisch verfügbar!
Interaktive Aufrufe vergleichen: Get-Process vs. Get-EventLog (hier dann Parameter als Eingabe möglich: Application, System, ...)
Get-Process
Get-EventLog
# Parameter - und einfache Parameter-Switches nutzen# Alle Aufrufe gleich:Get-ChildItem C:\temp *.txt # Hier: Reihenfolge entscheidend!Get-ChildItem -Path C:\temp -Filter *.txtGet-ChildItem -Filter *.txt -Path C:\temp# Verschiedene Platzhalter / Wildcards:Get-Process i*Get-Process i*oreGet-Process [st]*Get-Process [st][vf]*# Aktivieren / Deaktivieren von Schaltern:Get-ChildItem C:\temp -recurseGet-ChildItem C:\temp -recurse:$false
Allgemeine Parameter:
Aufrufe lassen sich zusammensetzen (später sinnvoll mit Variablen in Skripten)Get-ChildItem ("c:\" + "temp") *.txt –Recurse
Beispiel: ps ersetzt Get-Process (Unix-Shell lässt grüßen)
ps
Befehle zur Alias-Nutzung: Get-Alias ; Get-Alias psStandardanzahl für Aliase: 4096 (siehe Variable $MaximumAliasCount)
# Neue Aliase mit:Set-Alias procs Get-Process # neu oder überschreibenNew-Alias procs Get-Process
Wichtig: keine Parameter festlegbar - da brauchen wir später Funktionen! Der Übergabe-String für Aliase darf also keine Argumente enthalten.
Die Aliase gelten nur in der aktuellen PS-Sitzung (Session, Instanz). Bei nachhaltiger Nutzung müssen Aliase in Profile integriert oder manuell exportiert / importiert werden:
Export-Alias c:\temp\meinealias.csv # also in eine TextdateiExport-Alias c:\temp\meinealias.ps1 -as script # in ein PS-Skript# Laden:Import-Alias c:\temp\meinealias.csv. c:\meinealias.ps1 # Punktoperator - "Dot sourcing"
Es werden alle Aliase exportiert und wieder importiert, was zu "Fehlermeldungen" beim Import für die Standard-Aliase führt.
Man kann entweder manuelle Anpassungen der Exportdateien durchführen, so werden die Aliase "sauber" importiert, oder aber einfach später die gewünschten Aliase in den PS-Profilen sauber hinterlegen!Erster Tipp zur Unterdrückung der Fehlerausgaben: -ErrorAction SilentlyContinue
-ErrorAction SilentlyContinue
... eine erste Annäherung mit () im Expression bzw. Command Mode
Vergleiche:
Write-Output 10 * (8 + 6) # mit Write-Output (10 * (8 + 6))# Aufrufe mit Unterausdruck:"Anzahl der laufenden Prozesse: (Get-Process).Count"# vergleichen mit:"Anzahl der laufenden Prozesse: $((Get-Process).Count)"
Anm.: $ leitet also eine Subexpression (einen Unterausdruck) ein.
Auch hier wieder 32- und 64-Bit-Variante beachten! Integrated Scripting Environment (ISE - powershell_ise.exe) ist der Name des Skripteditors - mit PS 3.0 nochmals verbessert
[Anm. seit 202x: die ISE wurde von Microsoft abgekündigt. Daher sollten wir uns mit alternativen PowerShell Code-Editoren beschäftigen: Notepad++ oder am Besten gleich Microsoft Visual Studio Code!]
Stichworte zur ISE:
Wichtige Unterschiede zur normalen PowerShell Console:
Konfiguration der ISE:
# Eigene Farbgebungen in ISE mittels:$psISE.Options.ConsolePaneBackgroundColor = "red"# alternativ:$host.ui.RawUI.BackgroundColor = "red"
Siehe auch $psISE.options für die möglichen Einstellungen / Optionen der ISE Tipp: Einstellungen mittels Tools - Optionen bearbeiten bzw. auf Standard zurückstellen
$psISE.options
Übersichten und beispielhafte Aufrufe zu den PowerShell Providern und Drives ("Laufwerke") mittels
Get-PSProvider # PSProvider ÜbersichtGet-PSDrive # PSDrives ÜbersichtGet-PSDrive -PSProvider FileSystem # PSDrives FilesystemSet-Location Cert:\CurrentUser\Root # Wechsel in LW Cert:# Bei der Registry kann man den Provider auch direkt ansprechen:Get-ChildItem "REGISTRY::HKEY_CLASSES_ROOT\" -ErrorAction SilentlyContinue
Befehle zu Laufwerken, Items, Inhaltsobjekten und PfadenGet-Command –Noun *childitem, item*, path, content, location Übungen mit New-Item , New-PSDrive, Remove-PSDrive
Get-Command –Noun *childitem, item*, path, content, location
Erstellung eines neuen PSDrive: (in Folgeübungen)New-PSDrive -Name Skripte -PSProvider FileSystem -Root c:\temp\ps-skripte in der Profiltechnik unserer PowerShell (hier aktueller Host Console des aktuellen Users: $PROFILE)
New-PSDrive -Name Skripte -PSProvider FileSystem -Root c:\temp\ps-skripte
Sicherheitlevel beachten: siehe auch Get-Help Set-ExecutionPolicy
Cmdlets:
Die voreingestellte Policy (Richtlinie): Restricted - das würde aber gleich alle PowerShell-Skriptaufrufe (auch für unsere Profilskripte!) verhindern!
Also: mit Set-ExecutionPolicy (am Besten ohne Administrator Rechte!) die gewünschte Berechtigung RemoteSigned einstellen.
Set-ExecutionPolicy
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Anm.: ohne Angabe des Scope wäre es automatisch eine Konfiguration für die Maschine und somit nur mit Admin-Rechten möglich.Und gleich mit Get-ExecutionPolicy testen. Vollständige Analyse der PowerShell Policies mit
PS C:\Users\joeb> Get-ExecutionPolicy -List Scope ExecutionPolicy ----- --------------- MachinePolicy Undefined UserPolicy Undefined Process Undefined CurrentUser RemoteSigned LocalMachine Undefined
Die Policy-Level werden der Reihe nach von unten (LocalMachine) nach oben (GPO MachinePolicy für Computer) durchlaufen!
Anm.: bitte ggf. nicht die 32-Bit-PowerShell (x86) ExecutionPolicy vergessen!
Die Teilnehmer bekommen eine ausführliche Screenshotsammlung für das Seminar (ca. 200-300 Screenshots/Tag) zu Ihren digitalen Unterlagen!
Beispielhafte Screenshots aus Vorseminar PowerShell:
Eine kurze Erinnerung zum Thema PowerShell-Hosts: wir können der PowerShell eigene "Technikumgebungen" schneidern. In der Grundausstattung der Windows Systeme sind die folgenden (32-/64-Bit) Hosts verfügbar:
Sowohl die PowerShell (ConsoleHost) als auch die ISE (Windows PowerShell ISE) besitzen Profile (Profildateien / Konfigurationen). Außerdem kann man auch generelle Profile für alle User (AllUser) oder nur für den aktuellen (CurrentUser) konfigurieren.Anzeigen der Profile jeweils (!) mit Variable $PROFILE in der PowerShell ergibt:C:\Users\joeb\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
$PROFILE
C:\Users\joeb\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
In der ISE dann ebenfalls $PROFILE mitC:\Users\joeb\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
C:\Users\joeb\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1
Die komplette Übersicht erschließt sich mit den folgenden Aufrufen:
$PROFILE# genauer: (Anm.: siehe auch ISE)$PROFILE$PROFILE.CurrentUserCurrentHost$PROFILE.CurrentUserAllHosts$PROFILE.AllUsersCurrentHost$PROFILE.AllUsersAllHosts
Auf einem frischem System hat ein User noch kein Profil - siehe Test-Path $PROFILE (ergibt FALSE)
Test-Path $PROFILE
Effizientes Erstellen der $PROFILE inklusive notwendiger Ordner/Unterordner:New-Item -Path $PROFILE -ItemType File -force
New-Item -Path $PROFILE -ItemType File -force
Anpassen der Profile dann in weiteren Übungen, wenn wir das Skripten im Griff haben.Erste Übung mit Aliasen (Set-Alias) und Konfigurationen für die PowerShell...
Anm.: die Original-Windows-Installationen im Seminarraum VHS BS haben Benutzerordner (untypisch): D:\TN-Bibliotheken\Dokumente\WindowsPowerShell\... - wir nutzen (meist) frische, eigene Installationen.
Die PowerShell kann mit Objekttechnik arbeiten. Das sind Grundkonzepte aus Programmiertechniken und -Modellen und führen oft sehr weit in programmiertechnische Details. Das wollen wir vermeiden und wir benötigen diese Vertiefungen für die Anwendung der PowerShell nicht.
Eine einfache Heranführung an Objekte mit der PowerShell soll hier erfolgen - Objektmember sind klassisch:
(Get-ChildItem C:\temp).LastWriteTime
(Get-Date).AddYears(5)
In einem Vorseminar habe ich das Nachfragen von Trainees einmal versucht mit einem einfachen Beispiel (Scribble) darzustellen.
Die PowerShell kennt noch weitere Member für die Objekte außer Property und Method:
Anm.: die genauere Betrachtungen zu diesen Objekt-Members obliegen anderen PowerShell-Vertiefungen (bzw. siehe PowerShell Literatur) und sind - wie gesagt - für die Anwendungen der PowerShell erst einmal vernachlässigbar.
Wie können wir uns die Objekttechnik analysieren?
Anzeige von Eigenschaften mit Cmdlet Get-Member : Get-Process | Get-Member # Member nach dem Pipeline-Processing (s.o.)
Get-Member
Get-Process | Get-Member
An dieser Stelle in der Ausgabe bitte den TypeName (System-Klasse) beachten: System.Diagnostics.Process
Spezialität: Eigenschaften vor Pipeline-Processing anzeigen lassen:Get-Member -InputObject (Get-Process) # Member eines Get-Process-Objects (vor einem möglichen Pipelining)
Get-Member -InputObject (Get-Process)
Und für die Verbindung von PowerShell zu System-Klassen kann man den folgenden Aufruf ausprobieren:[System.Diagnostics.Process]::GetProcesses() Wir erhalten das Ergebnis des PowerShell Cmdlet Get-Process !
[System.Diagnostics.Process]::GetProcesses()
Oder wir versuchen das ganze mit einem einfach Cmdlet (Anm.: einfach, weil wir nur ein Objekt erhalten)[System.DateTime]::Now Das gleiche Ergebnis erhalten wir durch das PowerShell Cmdlet Get-Date ! (Ja ich weiß - die Sekunden passen nicht 😜 )
[System.DateTime]::Now
Get-Date
[PS-Experts] Die Ausgabe der genutzten Dot.Net-Systemklassen regelt eine XML-Datei für die PowerShell (systemweit):$PSHOME\DotNetTypes.format.ps1xml Einfach in dieser Datei nach den entsprechenden Klassen suchen (Strg + F) und schon kann man die Ausgaben nachvollziehen und/oder nach eigenen Wünschen mit zusätzlichen, eigenen Konfigurationen anpassen lassen! Tipp: Hilfe mit Get-Help about_Format.ps1xml aufrufen - lokal oder mit Parameter -Online .
$PSHOME\DotNetTypes.format.ps1xml
Get-Help about_Format.ps1xml
-Online
(Online-Beitrag - inkl. Pipeline-Bild - von Schwichtenberg auf entwickler.de)
In der PS ist alles objektorientiert bearbeitbar und wird über Pipeline-Processing weitergegeben.
Anm.: das besondere Konstrukt $_ greift auf das aktuelle Objekt zu.
$_
# komplexere Pipeline:Get-ChildItem c:\temp –r -filter *.txt | >>> Where-Object { $_.Length -gt 40000 } | >>> Select-Object Name, Length | >>> Sort-Object Length | >>> Format-List
Alternative: $PSItem als gleichwertiger Ersatz zu $_ (seit PS 3.0) - die PS-Anwender störten sich an dem "kryptischen Unterstrich".
$PSItem
Anm.: Erklärung für dieses Verhalten mit Get-Help Get-Service -full (siehe nach -name byValue und byPropertyName)
# Ein paar Beispiel für Pipeline-Aufrufe:Get-Process | >>> Where-Object {$_.name -eq "iexplore"} | >>> Format-Table ProcessName, WorkingSet64# Alle Prozesse, die mehr als 20 MB verbrauchenGet-Process | Where-Object {$_.WorkingSet64 -gt 20*1024*1024 }# kurze Varianteps | ? {$_.ws -gt 20MB }# alle Dienste, die mit i beginnen"i*" | Get-Service# Dienst "gleich" BITS"BITS" | Get-Service
Auch die klassischen Befehle lassen sich "pipen":netstat -an | Select-String "HERGESTELLT" -case (Select-String für reguläre Ausdrücke)
netstat -an | Select-String "HERGESTELLT" -case
Eigenschaften des Objekts ansprechen:(Get-Date).Year (als auch .Month, .Hour, .Minute)Anm.: keine Probleme mehr (also keine Fehlermeldungen, falls man denn mal mit einem Einzelobjekt arbeitet)
(Get-Date).Year
# Anzahl aller Prozesse(Get-Process).count# Anzahl von Prozessen mit mehr als 20 MB im RAM(Get-Process | where-object { $_.WorkingSet64 -gt 20MB }).Count# Objekte lassen sich dann mit Array-Technik einzeln ansprechen:(Get-Process | where-object { $_.WorkingSet64 -gt 20MB })[5]# früher:Get-Process | foreach-object {$_.Name }# seit PS 3.0:(Get-Process).Name# Für eine kombinierte Ausgabe ist foreach-Commandlet nötig:Get-Process | foreach-object {$_.Name + ": " + $_.Workingset64 }
Methoden der Objekte: (also Funktionen zu denen die Objekte fähig sind) Automatic Unrolling (seit PowerShell 3.0)
# Beispiel zu Automatic Unrolling$dll = Get-ChildItem C:\Windows\System32\*.dll | Select-Object -First 3$dll # Ausgabe# wieder 3 Versionen$dll.VersionInfo # ab PS 3.0$dll | Select-Object -ExpandProperty VersionInfo$dll | ForEach-Object { $_.VersionInfo }# Analyse$dll | Get-Member # hier sieht man VersionInfo / ScriptProperty – nach der Pipeline!# im Vergleich mit Get-Member –InputObject $dll # Get-Member kennt kein VersionInfo
Alle Techniken praktisch erprobt.
# alle iexplore "killen"Get-Process iexplore | Foreach-Object { $_.Kill() }# seit PS 3.0:(Get-Process iexplore).Kill()# besseres Commandlet: Stop-Process # hier gibt es auch keine Fehler mehr, falls kein iexploreGet-Process | Where-Object { $_.Name -eq "iexplore" } | Stop-Process# Alle Methoden für Get-Date anzeigen lassen:Get-Date | Get-Member(Get-Date).ToLongDateString() # und viele Andere
Anm.: die Fehlerbehandlung in unsere PowerShell Konsole wird durch Einsatz von PSReadline optimiert.
Siehe auch Google-Recherche "powershell vergleichsoperatoren" - beispielhafter Ergebnislink
Mit eingebauter PS-Hilfe: get-help about_Comparison_Operators -ShowWindow
get-help about_Comparison_Operators -ShowWindow
Kleine Übersicht:
gt
-ge
-lt
-le
-eq
-ne
-Like
-NotLike
-Match
-NotMatch
Mit vorgesetztem "c" (dann also -clike) kann man die Case-Sensitivity erzwingen, was auf Windows-System nicht viel Sinn ergibt.
Hier werden wir Variablen erst einmal interaktiv in der PS nutzen:
# Übersichtlichkeit schaffen - Vorarbeiten für SkriptingGet-Process | >>> Where-Object {$_.name -eq "iexplore"} | >>> Foreach-Object { $_.ws }# wird zu$x = Get-Process$y = $x | Where-Object {$_.name -eq "iexplore"}$z = $y | Foreach-Object { $_.ws }
Übungen zu den Variablen in Bezug auf Sichtbarkeit (Console vs. ISE) und mit Get-ChildItem Variable: Übersicht über die vorhandenen Variablen in einer PowerShell Host-Session
Get-ChildItem Variable:
Bestimmte Variablennamen sind nicht erlaubt $_ oder $PSItem (klar - brauchen wir für die Objekte)Commandlets: Set-Variable und Get-Variable sowie Clear-Variable
Variablen Read-Only: Set-Variable variablenname -Option readonly
Set-Variable variablenname -Option readonly
Typisierungen - Fachbegriff bei Programmiersprache (C, Java): Cast Operator
Vordefinierte Variablen:
Und natürlich können hier auch wieder weitere Eigenschaften aufgerufen/genutzt werden - z.B. $host.UI.RawUI.BackgroundColor = "darkgreen"
Erinnerung: Variablen werden in Zeichenketten mit doppelten Anführungszeichen ausgewertet - bei einfachen Zeichenketten nicht!
Mit den Standard-Cmdlets (Verben: Where-, Sort-, Group-) werden praktische Übungen durchgeführt:
# Prozesse, der Speicher größer als 10000000 Bytes Get-Process | Where-Object {$_.ws -gt 10000000 }# Inklusive Sortierung und Auswahl der ErgebnissätzeGet-Process | Sort-Object ws -desc | Select-Object -first 5Get-Process | Sort-Object ws -desc | Select-Object -last 5# mit Regulären Ausdrücken# Systemdienste, deren Beschreibung aus zwei durch ein Leerzeichen getrennten Wörtern besteht.Get-Service | Where-Object { $_.DisplayName -match "^\w* \w*$" }# Prozesse, deren Namen mit einem "i" starten und danach drei BuchstabenGet-Process | Where-Object { $_.ProcessName -match "^i\w{3}$" }Vergleichsoperatoren (s. about_Comparison_Operator)# klassische Filter:Get-Service | where-object { $_.status -eq "running" }# können seit PS 3.0 auch mitGet-Service | where-object status -eq "running"# aber bei Kombinationen mit and oder or bitte wieder klassisch:Get-Process | Where-Object { $_.Name -eq "iexplore" -or $_.name -eq "Chrome" -or $_.name -eq "Firefox" } | Stop-ProcessGet-Service | where-object { $_.status -eq "running" -and $_.name -like "a*" }#Objekte für Ausgaben einschränken ("kastrieren")Get-Process | Select-Object processname, minworkingset, ws | Get-Member# Prozesse nach Speicherverbrauch sortierenGet-Process | Sort-Object ws –desc# Mehrere SortierfelderGet-Service | Sort-Object Status, Displayname# mehrfach-Elemente finden - man muss immer erst sortieren!1,5,7,8,5,7 | Sort-Object | Get-Unique# Elemente gruppierenGet-Service | Group-Object status# Dateien in System32 nach Erweiterungen gruppieren und sortiert ausgebenGet-ChildItem c:\windows\system32 | Group-Object extension | Sort-Object count –descGet-ChildItem c:\windows\system32 | Select-Object extension -Unique# Auswertungen mit Measure-Object - Standard ist count, also AnzahlGet-ChildItem c:\windows | Measure-Object -Property length -min -max -average -sum
Insbesondere bei der Nutzung der Regulären Ausdrücke (Regular Expression - Wikipedia Link - Signalwort "match") kratzen diese Beispiele natürlich nur an der Oberfläche.
Wir testen zu den unterschiedlichen Typen diverse Aufrufe und Funktionen (Klassen):
# Zahlen - Int[Int32]::MaxValue# 2147483647[UInt32]::MaxValue# 4294967295[Int32]::MinValue# -2147483648[Byte][Char]’A’# 65[Byte[]][Char[]]’Hello’# 72 #101 #108 #108 #111 (untereinander)[Char[]](65..90)[Char[]]'Hello'[Byte[]][Char[]]'Hello'# Spezielle Daten mit Klasse System.Net.Mail.MailAddress$email = [System.Net.Mail.MailAddress]'Some User<Diese E-Mail-Adresse ist vor Spambots geschützt! Zur Anzeige muss JavaScript eingeschaltet sein.'
Weitere ausführliche Aufrufe und Techniken werden den Teilnehmern zur Verfügung gestellt!
Insbesondere mit $email.Displayname bzw. mit $email. Strg+Leertaste (Technik: PSReadline - Intellisense) erkennt man immer wieder die "Objekte / Eigenschaften", die in der PowerShell bei dem entsprechendem Objekt nutzbar sind.
$email.Displayname
$email. Strg+Leertaste
Erinnerung: siehe auch wieder die Online-Hilfen zu den Vorgehensweisen und Methoden:
# Das "Echo" für die PS: Write-HostWrite-Host "Guckst Du" -ForegroundColor Yellow # Zeichenketten Operationen (Methoden)"" | Get-Member -m Method[String] $CSVString = "Joe;Brandes;Braunschweig;Deutschland;www.pcsystembetreuer.de"$CSVArray = $CSVString.Split(";")$Surname = $CSVArray[1]$Surname
Das ließe sich dann auch gerne auf viele Datensätze/Zeilen anwenden.
Eine erste einfache Definition:
$a = 01,08,72,13,04,76
Das Array kann auch explizit mit [array] deklariert werden: [array] $b
[array] $b
Anzahl der Elemente in einem Array: $b.Count
$b.Count
Die Arrays stellen im Grunde einfache Tabellen dar. Hierbei stehen sich die Spalten Index und Werte gegenüber.
Das Assoziative Array (eine Hashtabelle) benutzt keine einfachen Index sondern Strings:
# Implicit Hashtable$Computers = @{ E01 = "192.168.1.10"; E02 = "192.168.1.20"; E03 = "192.168.1.30"; }# Explicit Hashtable[Hashtable] $Computers = @{ E01 = "192.168.1.10"; E02 = "192.168.1.20"; E03 = "192.168.1.30"; } $Computers["E02"]$Computers.E02
Also: Arrays sind 2-spaltige Tabellen mit Indizes (Linke Spalte) und Werten (Rechte Spalte). Sie stellen in vielen Skripten ein zentrales Werkzeug für die Verarbeitung von Informationen dar.
... mit der PowerShell verarbeiten. Ein paar kleine Beispiele:
Get-DateGet-Date -displayhint dateGet-Date -displayhint time$a = Get-Date "8/1/1972 12:11:10"$a.DayOfWeek # SaturdayGet-Date $a –Format dddd # Samstag$Dauer = New-TimeSpan -Days 10 -hours 4 -minutes 3 -seconds 50$jetzt = Get-Date$zukunft = $jetzt + $Dauer
Die Systemzeit kann man mit Set-Date (bei entsprechenden Berechtigungen) setzen.
Der folgende EventLog Aufruf nutzt Get-Date für die Einträge aus den letzten 12 Stunden:Get-EventLog -LogName System -EntryType Error -After (Get-Date).AddHours(-12)
Get-EventLog -LogName System -EntryType Error -After (Get-Date).AddHours(-12)
Was kann Get-Date? Erinnerung an Get-Member:Get-Date | Get-Member -MemberType *Method Methode nutzen:(Get-Date).ToShortDateString()
Get-Date | Get-Member -MemberType *Method
(Get-Date).ToShortDateString()
Installzeit (als Unix-Timestamp)$Path = 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion' Get-ItemProperty -Path $Path | Select-Object -ExpandProperty InstallDate
$Path = 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion'
Get-ItemProperty -Path $Path | Select-Object -ExpandProperty InstallDate
Funktionsbeispiel für Umrechnung in Echte Zeit: datetime_cookbook.pdf von Weltner (siehe digitale Unterlagen / Online-Recherchen):[Anm.: hier die function einfach als erste Code-Umsetzung praktisch mit Trainer austesten! Ausführliche Erklärungen zu Functions folgen.]
function ConvertFrom-UnixTime { param( [Parameter(Mandatory=$true, ValueFromPipeline=$true)] [Int32] $UnixTime ) begin { # $startdate = Get-Date –Date 01.01.1970 # "01/01/1970" $startdate = Get-Date -Year 1970 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0 } process { $timespan = New-TimeSpan -Seconds $UnixTime startdate + $timespan }}
Jetzt in echter Zeit:
$Path = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion" Get-ItemProperty -Path $Path | Select-Object -ExpandProperty InstallDate | ConvertFrom-UnixTime
Zeitzonen:
[System.TimeZoneInfo]::GetSystemTimeZones()[System.TimeZoneInfo]::Local([System.TimeZoneInfo]::Local).StandardName
Lokalisierte Zeitinfos:
[System.Enum]::GetNames([System.DayOfWeek])# deutsch0..6 | ForEach-Object { [Globalization.DatetimeFormatInfo]::CurrentInfo.DayNames[$_] }0..11 | ForEach-Object { [Globalization.DatetimeFormatInfo]::CurrentInfo.MonthNames[$_] }
Verfügbare Culture IDs
[System.Globalization.CultureInfo]::GetCultures(‘InstalledWin32Cultures’)# Übersetzen der IETF Language Tags[System.Globalization.CultureInfo]::GetCultureInfoByIetfLanguageTag(‘de-DE’)
Die Funktionen kapseln mehrere Abarbeitungsschritte und können später dann auch Parameter übergeben bekommen und Werte zurückgeben.
Hier erst einmal ein paar Beispiele ohne Parameterübergabe - bitte einfach wieder auch zu den Hilfen greifen
# Beispielfunktion cdd - Change Dir with Dialogfunction cdd { $shell = New-Object -comObject "Shell.Application" $options = 0x51 # Nur Dateisystem-Ordner - inklusive Edit-Box $loc = $shell.BrowseForFolder(0, "Wohin soll es gehen?", $options) if($loc) {Set-Location $loc.Self.Path}}
Das Beispiel kann über Suchbegriffe "Shell.Application" und/oder "BrowseForFolder" analysiert werden: Erklärung: bei $options = 0x41 entfernt man die Edit-Box am unteren Rand des cdd-Dialogfensters.
$options = 0x41
Das folgende Beispiel kann über die "Online-/Offline-Dokumentation about_functions" entnommen werden:
function Get-NewPix{ $start = Get-Date -Month 1 -Day 1 -Year 2015 $allpix = Get-ChildItem -Path $env:UserProfile\*.jpg -Recurse $allpix | where {$_.LastWriteTime -gt $Start}}
Erklärung: dieses kleine Beispiel zeigt uns alle jpg-Dateien in unserem Benutzerprofil, die nach einem Startdatum geändert worden sind.
Für eine stetige Verfügbarkeit der Funktionen brauchen wir erst einmal nur den Code in unser $PROFILE Startskript zu packen. Für eine große Anzahl an Funktionen wird dieses aber später störend und wir werden uns die Module für PowerShell erarbeiten.
Jetzt: die Funktionen werden ausführlich kommentiert und sauber implementiert!
Durch die saubere Zuweisung mit Kommentarblock in einer Funktion wird die komplette Hilfe und Intellisense nutzbar.
# aus Weltner S. 478function Get-CriticalEvent{<# .SYNOPSIS listet Fehler und Warnungen aus dem System-Ereignisprotokoll auf .DESCRIPTION liefert Fehler und Warnungen der letzten 48 Stunden aus dem System-Ereignisprotokoll, die auf Wunsch in einem GridView angezeigt werden. Der Beobachtungszeitraum kann mit dem Parameter -Hours geändert werden. .PARAMETER Hours Anzahl der Stunden des Beobachtungszeitraums. Vorgabe ist 48. .PARAMETER ShowWindow Wenn dieser Switch-Parameter angegeben wird, erscheint das Ergebnis in einem eigenen Fenster und wird nicht in die Konsole ausgegeben .EXAMPLE Get-CriticalEvent liefert Fehler und Warnungen der letzten 48 Stunden aus dem System-Ereignisprotokoll .EXAMPLE Get-CriticalEvent -Hours 100 liefert Fehler und Warnungen der letzten 100 Stunden aus dem System-Ereignisprotokoll .EXAMPLE Get-CriticalEvent -Hours 24 -ShowWindow liefert Fehler und Warnungen der letzten 24 Stunden aus dem System-Ereignisprotokoll und stellt sie in einem eigenen Fenster dar .NOTES Dies ist ein Beispiel aus Tobias Weltners' PowerShell Buch .LINK http://www.powertheshell.com#> param($Hours=48, [Switch]$ShowWindow)if ($ShowWindow) { Set-Alias Out-Default Out-GridView } $Heute = Get-Date $Differenz = New-TimeSpan -Hours $Hours $Stichtag = $Heute - $Differenz Get-EventLog -LogName System -EntryType Error, Warning -After $Stichtag | Select-Object -Property TimeGenerated, Message | Out-Default }
Ausführliche Hilfe lässt sich durch die Kommentierungen nutzen:Get-Help Get-CriticalEvent -Full
Get-Help Get-CriticalEvent -Full
Die Funktionen lassen sich auch über das Laufwerk function: analysieren:(Get-Item function:\Get-CriticalEvent).Definition oder auch Get-Content function:\Get-CriticalEvent
function:
(Get-Item function:\Get-CriticalEvent).Definition
Get-Content function:\Get-CriticalEvent
Diese Techniken werden wir immer wieder benötigen.
Beispielhafte Screenshots aus Vorseminar PowerShell in 2019:
Wir vertiefen unser Verständnis mit weiteren Beispiel-Funktionen
Besondere Erwähnung: Datentyp [Switch] zum Überschreiben eines Cmdlet Out-Default mit Alias Out-Default (= Out-GridView).
Empfehlung: Verbesserung der Bezeichner (auch bei Dateien) mit Prefixen:
Durch die Prefixe lassen sich Kommandos noch leichter finden: Get-Command *-JB*
Get-Command *-JB*
Mit diesen Befehlen erhalten unsere Aufrufe Logik, Verschachtelungen und Schleifen.
Beispiele kann man auch über die PowerShell-Hilfe finden: (siehe) Get-Help about_if -Full oder Get-Help about_for -Full
Get-Help about_if -Full
Get-Help about_for -Full
Verzweigungen
Schleifen
Beispiele für Trainees digital verteilt und durchgesprochen. Hinweis auf Darstellungen eigener PowerShell-Website/-Doku und GitLab-Repo von Trainer Joe Brandes.
Literaturhinweis: Schwichtenberg (ab S. 132ff) oder online https://technet.microsoft.com/de-de/library/hh847732.aspx
Anm.: Vergleichsoperatoren bereits (s.o.) behandelt.
Hilfe mit Get-Help about_Operators bzw. Online https://learn.microsoft.com/de-de/powershell/module/microsoft.powershell.core/about/about_operators
& Aufrufoperator
Führt einen Befehl, ein Skript oder einen Skriptblock aus.
C:\PS> $c = "get-executionpolicy" C:\PS> $c get-executionpolicy C:\PS> & $c AllSigned
. Punkt-Quellen-Operator, Dot Sourcing
Führt ein Skript im aktuellen Bereich aus, sodass alle vom Skript erstellten Funktionen, Aliase und Variablen dem aktuellen Bereich hinzugefügt werden.
. c:\scripts.sample.ps1
Formatoperator –f
Formatiert Zeichenfolgen mit der Formatmethode von Zeichenfolgeobjekten.
C:\PS> "{0} {1,-10} {2:N}" -f 1,"hello",[math]::pi 1 hello 3.14
Anm.: die Ausgabe durch den Formatoperator fühlt sich erst einmal etwas umständlich an, stellt aber tatsächlich eine sehr effiziente Ausgabetechnik dar und wird auch in anderen Skriptsprachen so oder ähnlich umgesetzt (z.B. PHP mit sprintf).
Indexoperator [ ]
Wählt Objekte aus indizierten Datengruppen wie Arrays und Hashtabellen aus.
C:\PS> $a = 1, 2, 3 C:\PS> $a[0] 1
.. Bereichsoperator
Stellt die ganzen Zahlen eines Ganzzahlen-Arrays der Reihe nach dar, wobei eine obere und untere Grenze gilt.
PS E:\_temp> 1..3 1 2 3
Pipeline-Operator |
Sendet die Ausgabe des vorangegangenen Befehls via Pipe an den nachfolgenden Befehl. Wenn die Ausgabe mehrere Objekte (eine Datengruppe) enthält, sendet der Pipeline-Operator die Objekte einzeln nacheinander.
:: Operator für statische Member
Ruft den Operator für statische Eigenschaften und die Methoden der .NET Framework-Klasse auf.
[datetime]::now
Teilausdruckoperator $, Subexpression
Gibt das Ergebnis einer oder mehrerer Anweisungen zurück.
Verschiedene Wege führen hier zum Ziel: Umleitungsoperator ist > (Ersetzen) bzw. >> (Anhängen):
>
>>
Get-Process | Out-File "c:\temp\prozessliste.txt"# Ausgaben anhängen mit -AppendGet-Process | Out-File "c:\temp\prozessliste.txt" -Append
Umleitung der Pipeline-Ausgabe in verschiede Pipeline-Kanäle
Anm.: Umleitung an Drucker mit Out-Printer
Out-Printer
Beispiele für das Umleiten von Fehlern:
# Fehler in Datei umleitencat c:\temp\datei-exist-nicht.txt 2>> C:\temp\fehler.txt# Ausgabeströme umleitendir u:\Daten 2>&1 | Format-Table > C:\temp\prozessliste.txt
Tipp: Aufrufe testen: Tee-Object - zweigt Zwischenergebnisse in Dateien oder Variablen ab
Tee-Object
Weitere Ausgabtechniken - siehe wieder Get-Command Out-*
Cmdlets für Formatierungen:
Format-Wide
Format-List
Format-Table
Tabellenausgabe:
# Gezieltes Ausgeben der Tabellen - Propierties (Methoden)Get-Service | Select-Object -first 5 | Format-TableGet-Service | Select-Object -first 5 | Format-Table *Get-Service | Select-Object -first 5 | Format-Table -property Name, CanStop# Standardausgabe gemäß DotNetTypes.Format.ps1xml (eigentlich also DOT.NET Formate!)Get-ViewDefinition System.Diagnostics.ProcessGet-Process | Format-Table –view priority# Ausgaben einschränkenGet-Process | Format-Table -Property id,processname,workingset # als auchGet-Process | Select-Object id, processname, workingset | Format-Table # Seitenweise Ausgabe - oft sehr viel geschickter als altes moreGet-Service | Out-Host -Paging
Ausgabe-Commandlets in Host/Konsole
Write-Host
Write-Warning
Write-Error
Mit Write-Host manuelle Konfiguration möglich:Write-Host "Hallo Joe" -foregroundcolor red -backgroundcolor white
Write-Host "Hallo Joe" -foregroundcolor red -backgroundcolor white
Interessanter Parameter: -NoNewLine (kein Zeilenumbruch mit Write-Host)
-NoNewLine
Es folgen ein paar beispielhafte Codes - Highlight: Benutzerdefinierte Ausgabeformatierung mit @-Symbol
$a = "Joe Brandes"$b = "info(at)pcsystembetreuer.de"$c = Get-Date# wieder: in doppelten Zeichenketten sind Variablen nutzbar$a + " ist erreichbar unter " + $b + ". Diese Information hat den Stand: " + $c + ".""$a ist erreichbar unter $b. Diese Information hat den Stand: $c."# Neu: mit Platzhaltern und Formatbezeichnern: Ausgabeoperator -f"{0} ist erreichbar unter {1}. Diese Information hat den Stand: {2:D}." -f $a, $b, $c# weitere FormatierungenGet-Process | ForEach-Object { "{0,-40} | {1}" -f $_.Name, ($_.ws/1MB)}Get-Process | ForEach-Object { "{0,-40} | {1:n}" -f $_.Name, ($_.ws/1MB)}Get-Process | ForEach-Object { "{0,-40} | {1:0.000}" -f $_.Name, ($_.ws/1MB)}# Benutzerdefinierte Ausgabeformatierung mit @-Symbol:Get-Process | sort workingset64 -desc | ft @{Label="Nr"; Expression={$_.ID}; Width=5}, @{Label="Name"; Expression={$_.Processname}; Width=20 }, @{Label="Speicher MB"; Expression={$_.WorkingSet64 / 1MB}; Width=11; Format="{0:0.0}" }# Unterobjekt mit eigenen Methoden und Eigenschaften richtig ausgeben:Get-Process | ft ProcessName, { $_.TotalProcessorTime.Hours }
Tipp: Bitte immer wieder mit manuellen Anpassungen die Wirkungen testen und Hilfen bemühen.
Ausgaben unterdrücken
Unterschiedliche Techniken, um die Ausgabe von Skriptcode zu verhindern:
# Out-Null verwenden:Commandlet | Commandlet | Out-Null# Variable zugewiesen: $a = Commandlet | Commandlet# Typ [void] nutzen:[void] (Commandlet | Commandlet)# $null zuweisen:$null = Commandlet | Commandlet
Übungen mit unterschiedliche Eingaben / Interaktionen mit der PowerShell:
# Eingaben# ========# in Shell: Standardeingaben mittels Read-Host (Typ: System.String) $name = read-host "Bitte Benutzernamen eingeben:" # Standardeingaben verschlüssel mittels Read-Host (Typ: System.Security.SecureString) $kennwort_verschluesselt = read-host -assecurestring "Bitte Kennwort eingeben:" # Das verschlüsselte Kennwort wieder zurückholen [String]$kennwort_unverschluesselt = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($kennwort_verschluesselt)) "Kennwort: " + $kennwort_unverschluesselt # GUI: mittels .NET Framework in der Klasse Microsoft.VisualBasic.Interaction [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") $eingabe = [Microsoft.VisualBasic.Interaction]::InputBox("Bitte geben Sie Ihren Namen ein!") "Hallo $Eingabe!" # Dialogfenster (auch mit Dot.NET) [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") [System.Console]::Beep(15440, 30) [System.Windows.Forms.MessageBox]::Show("Gleich kommt eine Frage","Vorwarnung", [System.Windows.Forms.MessageBoxButtons]::OK) $antwort = [System.Windows.Forms.MessageBox]::Show("Nachricht","Ueberschrift", [System.Windows.Forms.MessageBoxButtons]::YesNo) if ($antwort -eq "Yes") { "Sie haben zugestimmt!" } else { "Sie haben abgelehnt!"
Insbesondere der Datentyp System.Security.String kann auch in anderen Anwendungen von Interesse sein. Hierfür kann man sich als Beispiel die Modulerweiterung für WSMan-Zugriffe auf einen "Tresor (Vault)" einer KeePass-Datenbank erarbeiten:GitHub-Projekt JustinGrote/SecretManagement.KeePass zeigt die wichtigsten Schritte.Tipp: vorher das Verständnis für PowerShell-Module bereitstellen.
System.Security.String
Die Bedeutung von Parameter -Credential bzw. Cmdlet Get-Credential für Zugriffe mit Authentifizierungen wird in Seminaren ausgearbeitet.
-Credential
Get-Credential
In Kürze: Module sind Ordner mit PowerShell Zusatztechnik.
Get-Module
Get-Module -ListAvailable
Alle Pfade für Modules (-Ordner): $env:PSModulePath aufrufen und mit geschickt mit $env:PSModulePath.split(";") einzeln darstellen lassen
$env:PSModulePath
$env:PSModulePath.split(";")
($env:PSModulePath).Split(";")# C:\Users\Benutzer\Documents\WindowsPowerShell\Modules# C:\Program Files\WindowsPowerShell\Modules# C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\
Wichtige Erkenntnis: die Module können also auch in einem Benutzerkonto-Ordner (Documents) abgelegt werden.
Der notwendige Ordner ist schnell angelegt:New-Item -path $env:PSModulePath.split(";")[0] -ItemType Directory -Force
New-Item -path $env:PSModulePath.split(";")[0] -ItemType Directory -Force
Die Module sind dann später jeweils in Unter-Ordnern organisiert. In den bestehenden (System-)Modul-Ordnern kann man hierfür auch Beispiele einsehen.
Nutzer können also mit Cmdlets eigene Module suchen (Find-Module) und bereitstellen:Save-Module -Path ($env:PSModulePath).Split(";")[0] -Name PSWindowsUpdate
Find-Module
Save-Module -Path ($env:PSModulePath).Split(";")[0] -Name PSWindowsUpdate
Es lohnt sich die automatisch entstandene Ordner-/Dokument-Struktur zu analysieren: Ordnerstruktur; *.ps1, *.psd1, *.psm1, *.ps1xml
Eine erste Empfehlung: Modul PSCX (PowerShell Community Extension)
Einfacher Bauplan: hier: ein Modul mit nur einer Funktion! - in diesem Seminar nicht als Praxis, sondern gleich die komplette Modultechnik (s.u.)
Für die folgenden Erstellungen muss der PowerShell-Host die Funktion kennen!Hier: Get-CriticalEvent – Fehler und Warnungen aus System-Ereignisprotokoll – letzte 48 Stunden).
# folgende Befehle in Umgebung, wo Funktion Get-CriticalEvent bekannt ist!# Funktion siehe oben...$name = 'Get-CriticalEvent'$path = Split-Path -Path $profile$code = "function $name { $((Get-Item function:\$name).Definition) }"New-Item -Path $path\Modules\$name\$name.psm1 -ItemType File -Force -Value $code# Erster Test für die Verfügbarkeit des Cmdlet per Modul:Get-Module get-cr* -ListAvailable
Natürlich möchte man nicht nur eine Funktion pro Modul!
Praxis/Übung: Bauplan für komplette Modultechnik: (im Seminar als ausführliche Praxisübung inklusive PDF-Print-Anleitung!)Anm.: Ausführliche Darstellung zu kompletten Modulen Siehe auch "Weltner, Kapitel 17 - Eigene Module erstellen; ab S. 589ff" oder auch in meinen "Scriptlines" als digitales Begleitmaterial für unsere Teilnehmer.
Modul-Ordner: C:\Users\username\Documents\Windows PowerShell\Modules\MyTools bzw. $HOME\Documents\Windows Powershell\Modules\MyTools oder $env:PSModulePath.split(";")[0]
C:\Users\username\Documents\Windows PowerShell\Modules\MyTools
$HOME\Documents\Windows Powershell\Modules\MyTools
$env:PSModulePath.split(";")[0]
mit Manifest-Datei: .\MyTools.psd1 (erstellt mit Cmdlet New-ModuleManifest )und Konfigurationen für
.\MyTools.psd1
New-ModuleManifest
RootModule='MyTools.psm1' FunctionsToExport='*'
und Module-Datei: .\MyTools.psm1 mit Aufrufen für die einzelnen Funktionsdateien
.\MyTools.psm1
. $PSScriptRoot\myfunc1.ps1. $PSScriptRoot\myfunc2.ps1
mit Funktionen-Dateien: myfunc1.ps1, myfunc2.ps1, ... (enthalten die Funktions-/Cmdlet-Definitionen)
myfunc1.ps1
myfunc2.ps1
Anm.: das automatische Loading der Module funktioniert auch nach einmaligem erzwungenen Import-Module MyTools -Force -Verbose leider nicht mehr sauber auf allen Versuchsrechnern!Empfehlung: Import-Module MyTools für unser $PROFILE bzw $PROFILE.... (Hosts oder sogar Systemumgebung).
Import-Module MyTools -Force -Verbose
Import-Module MyTools
Plan / To-Do-List für Freitag:
... schauen wir mal ...
Get-WmiObject
Get-CimClass
Die klassische WMI (Windows Management Interface) und die "allgemeine" Variante CIM (Common Information Model) bieten Zugriff auf Tausende von Klassen mit Zugriff auf Systeminformationen und -Techniken:Get-WmiObject -Class Win32_Bios -Computername DC01 (also gleich mit eingebautem "Fernzugriff")
Get-WmiObject -Class Win32_Bios -Computername DC01
Auf aktuellen Windows-Betriebssystemen kann man mit WMI/CIM-Techniken auf rund 1200 Klassen zugreifen.
Get-WmiObject -List
Get-CimInstance
Beispielhafte Aufrufe:
# Service Start Modi - Anmerkung: Get-Service kannte keinen StartMode!Get-WmiObject Win32_Service | Select-Object Name, StartMode# ein spezieller Startmodus([wmi]'Win32_Service.Name="Spooler"').StartMode# eingeloggte User$ComputerName = ‘localhost’Get-WmiObject Win32_ComputerSystem -ComputerName $ComputerName | Select-Object -ExpandProperty UserName# Netzwerkanalysefunction Get-NetworkConfig {Get-WmiObject Win32_NetworkAdapter -Filter ‘NetConnectionStatus=2’ |ForEach-Object { $result = 1 | Select-Object Name, IP, MAC $result.Name = $_.Name $result.MAC = $_.MacAddress $config = $_.GetRelated(‘Win32_NetworkAdapterConfiguration’) $result.IP = $config | Select-Object -ExpandProperty IPAddress $result }}# Lokale GruppenGet-WmiObject Win32_Group -Filter "domain='$env:computername'" | Select-Object Name,SID# Uptime Os$os = Get-WmiObject -Class Win32_OperatingSystem$boottime = [System.Management.ManagementDateTimeConverter]::ToDateTime($os.LastBootupTime)$timedifference = New-TimeSpan -Start $boottime$days = $timedifference.TotalDays'Das System läuft seit {0:0.000} Tagen.' -f $days# Freier Speicher auf DisksGet-WmiObject Win32_LogicalDisk | ForEach-Object { ‘Disk {0} hat {1,20:0.00} MB Platz frei’ -f $_.Caption, ($_.FreeSpace / 1MB)}
Weitere Quellen zum Technik-Thema WMI / CIM:
Hinweis auf PowerShell Cookbook PDFs von Autor Weltner (Link)
Über die $PSHOME\*.ps1xml Dateien werden die Formate und Aufbereitungen der unterschiedlichen PowerShell Techniken (z.B. Dot.Net) bereitgestellt.
$PSHOME\*.ps1xml
Diese Vorgaben kann man erweitern - Links zum Thema:
Plan: für das Standard-Cmdlet Get-ChildItem wollen wir eine zusätzliche Eigenschaft (Property bzw. genauer ScriptProperty) für das Alter (Age) einer Datei erzeugen.
Get-ChildItem
Wir erzeugen eine neue Definition per eigener *.ps1xml Datei - z.B.: ~/Documents/ps-skripte/MyTypes.ps1xml
~/Documents/ps-skripte/MyTypes.ps1xml
<?xml version="1.0" encoding="utf-8" ?> <Types> <Type> <Name>System.IO.FileInfo</Name> <Members> <ScriptProperty> <Name>Age</Name> <GetScriptBlock> ((Get-Date) - ($this.CreationTime)).Days </GetScriptBlock> </ScriptProperty> </Members> </Type> </Types>
Wir nutzen die Datei:
Update-Typedata -PrependPath ~/Documents/ps-skripte/MyTypes.ps1xml
Wir erhalten ein neues ScriptProperty Age!
Get-ChildItem $PSHOME\powershell.exe | Select-Object Age
Die Updates für unsere Datentypen müssen beim Start einer PowerShell-Session berücksichtigt werden.
Nachfrage Trainee: die Standard-Ausgabe von (z.B.) Get-ChildItem führt zu den Tools rund um die TypeData-Cmdlets:
Get-Command -Module Microsoft.PowerShell.Utility -Name *data*
Die Tools zu TypeData und FormatData können bei diesen Ideen weiterhelfen.
... Backgroundjobs - können möglicherweise Skriptlaufzeiten (massic) positiv beeinflussen
Vorbereitete Übung ... Siehe Übungsdateien TN und Script-Sammlung für TN
... mit der PowerShell verwalten.
Unterschiedliche Techniken möglich:
Commandlets mit eingebauter Funktionalität (Parameter -ComputerName) für Fernaufrufe
auf anderen Maschinen
# Commandlets mit eingebauter "Fernwartung"Get-Command | where { $_.parameters.keys -contains "ComputerName" -and $_.parameters.keys -notcontains "Session"}# Aufrufbeispiel: (auch gerne gleichzeiig auf mehreren Maschinen)Get-Service -ComputerName domvbox-2012r2 i*
Bedenken: nur in Domänenumgebungen sind die Authentifizierungen vorhanden - ansonsten werden Übergaben von "Credentials" mit Comdlet Get-Credential benötigt.
Praktische Übungen mit den WMI/CIM-Cmdlets: hier beachten, dass Get-WmiObject "Credentials" übergeben kann. Aber Get-CimInstance kann keine Credentials übergeben.
PowerShell Sessions - die moderne MS Terminalsitzung / Shellsession
Wichtig: in P2P-Netzen - also ohne Windows Domäne - muss auch die Erlaubnis der gegenseitigen Zugriffe mittels TrustedHosts im WSMan(ager) konfigurieren und Testen, bevor man die Zugriffe per WinRM nutzen kann! Kurzanleitung:
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "10.100.211.116, Win10" -Force#ggf. Testen/Restarten WinRM: Restart-Service WinRM# Einfacher TestTest-WSMan -ComputerName # eigener RechnerTest-WSMan -ComputerName 10.100.211.116 # Gegenstelle
Technikhintergrund: WinRM (Windows Remote Management)
Mindest-Anforderungen für WinRM Services: Microsoft .NET Framework 2.0 oder höher; Windows PowerShell 2.0 oder höher; Windows Remote Management (WinRM) 2.0
Rechner für PowerShell Sessions (PSRemoting) vorbereiten:
# WinRM-Systemdienst starten (inkl. Firewall - Netzwerkverbindungstyp beachten - kein Öffentliches Profil!)Enable-PSRemoting# Unterdrücken der Nachfragen und aktueller Netzwerkprofile-Checks mitEnable-PSRemoting -SkipNetworkProfileCheck -force# Testen der Fähigkeit:New-PSSession # bzw.: Test-WSMan
in Firmen/Domänen kann man die folgende Gruppenrichtlinie nutzen:Computer Configuration\Administrative Templates\Windows Components\Windows Remote Management (WinRM)\WinRM serviceBeispielhafte Nutzung:
# Interaktiv Sitzung:Enter-PSSession –Computername domvbox-2012r2# komplette Anmeldung inkl. -Credential und oft auch -Authentication# in Domänen: zentrale Verwaltung der Rechte! Normaler Weise kein Cred nötig!Enter-PSSession domvbox-2012r2 -Authentication Negotiate -credential dom2012r2\Administrator# Beenden:Exit-PSSession# aktuelle Konsolenmaschine[System.Environment]::MachineName
Alternative Aufrufe und weitere technische Möglichkeiten mittels Commandlet Invoke-Command Anregung: Recherche nach Cmdlets mit *PSSession*
Invoke-Command
PowerShell WebAccess (PSWA)
Zugriff auf PowerShell-Console mittels https-Web-Client (Browser) vergleichbar zu OWA (Outlook Web Access)Notwendige Installationen:
mit PowerShell: Install-WindowsFeature -name web-server, windowspowershellwebaccess
Install-WindowsFeature -name web-server, windowspowershellwebaccess
Weitere Konfigurationen:
# Installieren/Bereitstellen von Test-ZertifikatInstall-PswaWebApplication -UseTestCertificate# Anm.: jetzt Server erreichbar unter https://localhost/pswa # Regel (hier sehr "frei") für die Erreichbarkeit von PSWA erstellen:Add-PswaAuthorizationRule –UserName * -ComputerName * -ConfigurationName *
Beim Aufruf der Webseite https: // dc-server/pswa muss man natürlich das Zertifikat im Browser anerkennen (lassen).
https: // dc-server/pswa
Für den Zugriff auf einen "Server" benötigt man also nur einen Web-Client und schon kann es losgehen.
RSAT in Windows Domänen auf WinClients
RSAT - Remoteserver Administration Tools - Download RSAT für Windows 10 - bitte Windows-Version beachten!Ab Windows 10 (1809) kein eigenständiger Download mehr (Info-Link), sondern "WindowsCapability" Erweiterungen hinzufügen:
Get-WindowsCapability -Online | Where-Object {$_.Name -like "*RSAT*" -and $_.State -eq "NotPresent"} | Add-WindowsCapability -Online
Analyse Anzahl Commandlets/Functions: Windows 8.1 hatte 1264 Mit Windows 8.1 + RSAT zählte dann 2211 (!) und RSAT stellt mit dem "Active Directory-Verwaltungscenter" die moderne AD-Verwaltung mit Sicht auf die PowerShell-Befehle bereit (Windows PowerShell Verlauf History)
Beispiel für AD-Commandlet aus Modul "ActiveDirectory": Get-ADUser -Filter { Name -like "*Joe*" }
Get-ADUser -Filter { Name -like "*Joe*" }
... stellt auf einem AD Domain Controller (DC) direkt Cmdlets zur AD-Verwaltung bereit.
Auf einem Mitgliedsserver über hinzufügen von Features das PowerShell-Modul "ActiveDirectory" bereitstellen oder auf Clients (Windows 7 Professional, Windows 10 Pro) die passenden RSAT-Tools installieren/bereitstellen.
Exemplarische Codebeispiele / PowerShell-Nutzungen:
Hinweise zu den AD-Cmdlets:
-recursive
-confirm:$false
Set-Location 'DC=dom2012r2,DC=local'
Recherche auf DC-Verwaltung mit Active Directory-Verwaltungscenter (dsac.exe): dort kann man mittels der unten eingeblendeten "Windows PowerShell-Verlauf History" die nötigen PowerShell Aufrufe durch Tests mit AD-Objekten protokollieren lassen und für eigene Umsetzungen entnehmen.
dsac.exe
Hand-Outs Trainer J. Brandes
Allgemeine Unterlagen
Letzte TN-Fragen, Feedback-Bögen, TN-Bescheinigungen
Die Teilnehmer bekommen eine ausführliche Screenshotsammlung für das Seminar (ca. 250-300 Screenshots/Tag) zu Ihren digitalen Unterlagen!
Die praktischen Umsetzungen zum "Aufmotzen und Tweaken" der PowerShell werden im Seminar gemeinsam mit den Trainees erarbeitet.
Ausführlichere Umsetzungen und Hinweise habe ich auf meiner PowerShell Extra-Site untergebracht - siehe Profile und Module.
Hier ein paar "Side-Topics" für die praktischen Durchführungen im Seminar:
Install-Module posh-git -Scope CurrentUser
Install-Module oh-my-posh -Scope CurrentUser
# PowerShell powerline-go stuff# see: https://docs.microsoft.com/de-de/windows/terminal/tutorials/powerline-setup# do:# Install-Module posh-git -Scope CurrentUser# Install-Module oh-my-posh -Scope CurrentUser# if on PowerShell core:# Install-Module -Name PSReadLine -AllowPrerelease -Scope CurrentUser -Force -SkipPublisherCheckImport-Module posh-gitImport-Module oh-my-posh# Alternativen: Set-Theme ParadoxSet-Theme Powerlevel10k-Classic
z
Install-Module zlocation -Scope CurrentUser
Import-Module ZLocationWrite-Host -Foreground Green "`n[ZLocation] knows about $((Get-ZLocation).Keys.Count) locations.`n"
Anm.: ggf. später mehr hierzu als Links und Screenshots nach Seminaren
Quellen aus den Seminaren, die ich an dieser Stelle darstellen möchte.
Die Bücher werden auch im Seminar mit den Teilnehmern eingeschätzt: (s.a. unten als Bilder-Gallery)
Gebundene Ausgabe 2. Juni 2016 Dr. Tobias Weltner: 1158 Seiten Verlag: O'Reilly; Auflage: 2., akt. Aufl. (2. Juni 2016) Sprache: Deutsch ISBN-10: 3960090099 ISBN-13: 978-3960090090
Gebundene Ausgabe – 11. Mai 2020Dr. Holger SchwichtenbergGebundene Ausgabe: ca. 1400 Seiten (!!)Verlag: Carl Hanser Verlag GmbH & Co. KGSprache: DeutschISBN-10: 3446459138ISBN-13: 978-3446459137
Das PowerShell-Praxisbuch für Einsteiger und Profis - jetzt in der 4. Auflage für PowerShell 5 (und jetzt Core 7)
The Complete Guide to Scripting Microsoft's Command Shell (Englisch) Taschenbuch – 8. Januar 2013von Lee HolmesTaschenbuch: 1034 SeitenVerlag: O'Reilly & Associates; Auflage: 3 (8. Januar 2013)Sprache: EnglischISBN-10: 1449320686ISBN-13: 978-1449320683
oreillys basics Broschiert – 28. März 2007von Andy Oakley (Anm.: als Beispiel für eine sehr ordentliche Einstiegslektüre - natürlich nicht mehr aktuell!)Broschiert: 240 SeitenVerlag: O'Reilly; Auflage: 1 (28. März 2007)Sprache: DeutschISBN-10: 3897214873ISBN-13: 978-3897214873
Falls Sie Anregungen hinsichtlich Büchern und Webseiten haben, dann bitte einfach per Mail an mich melden.
Keep on PowerShelling...Ihr Trainer Joe Brandes
Sie finden auf dieser Seite - als auch auf meiner privaten Visitenkarte joe-brandes.de einige Hintergrundinformationen zu mir und meinem Background.Natürlich stellt die IT einen Schwerpunkt in meinem Leben dar - aber eben nicht nur ...
Private Visitenkarte / Technik: HTML & CSS joe-brandes.de
Ich erarbeite und konzipiere seit über 30 Jahren IT-Seminare und -Konzepte. Hierfür stehen der "PC-Systembetreuer / FITSN" und der "CMS Online Designer / CMSOD". Ich stehe Ihnen gerne als Ansprechpartner für Ihre Fragen rund um diese und andere IT-Themen zur Verfügung!
BECSS Visitenkarte / Technik: HTML & CSS becss.de
Wer einmal zum Snookerqueue gegriffen hat, der wird es wohl nicht wieder weglegen. Und ich spiele auch immer wieder gerne eine Partie Billard mit den Kumpels und Vereinskameraden. Der Verein freut sich über jeden, der einmal in unserem schicken Vereinsheim vorbeischauen möchte.
Billard Sport BS / nicht mehr von mir betreut billard-bs.de