Bevorstehendes Webinar: Transformiere dein Microsoft Teams Management mit PowerShell
ScriptRunner Blog
Erweiterte Funktionen in PowerShell
Inhaltsverzeichnis
Erweiterte PowerShell-Funktionen bieten die Möglichkeit, ein einfaches PowerShell-Script zu einem Tool zu erweitern, das sich wie ein natives PowerShell-Cmdlet verhält. Mit den erweiterten PowerShell-Funktionen können reguläre Scripts denselben Satz von Funktionen verwenden, der für systemeigene Cmdlets verfügbar ist.
Die erweiterten PowerShell-Funktionen basieren auf vier Säulen.
- Stream-Steuerung
- Parameter-Validierung
- Pipeline-Bindung
- Safeguards
In den folgenden Abschnitten werden diese ausführlicher behandelt.
Stream-Steuerung
Die PowerShell-Engine stellt eine Reihe von Streams bereit, die je nach Kontext zum Senden verschiedener Nachrichten verwendet werden können.
- Output / Success
- Error
- Warning
- Verbose
- Debug
In Abhängigkeit vom Kontext können eingebaute Cmdlets dazu verwendet werden, um in einen bestimmten Stream zu schreiben. Wenn wir beispielsweise in den Verbose-Stream schreiben möchten, können wir das Cmdlet „Write-Verbose“ usw. verwenden.
Es reicht jedoch nicht aus, nur das richtige Cmdlet zu verwenden, wie man in Abbildung 1 sehen kann.
Function Do-SomethingRegular{ [CmdletBinding()] param( [String]$Message ) Write-Verbose "We are going to write the message by the User" Write-Output $Message } Do-SomethingRegular -Message "Hi Mom" -Verbose
Das CmdletBinding-Attribut stellt eine Reihe von Funktionen bereit, die von der PowerShell-Engine bereitgestellt werden. Man kann sagen, dass das CmdletBinding-Attribut unsere Funktion erweitert.
Wie man in Abbildung 2 sehen kann, schreibt unsere Funktion korrekt in den Verbose-Stream.
Aber was wäre, wenn wir das Script beenden wollten, sobald wir auf den nicht-terminierenden Fehler stoßen?
Die Lösung besteht darin, den Wert der ErrorActionPreference-Variablen auf „Stop“ zu ändern.
Die Änderung dieser Variable hat jedoch Auswirkungen auf alle anderen Scripte auf dem System, da es sich um eine globale Variable handelt. Dieses Problem lässt sich dadurch lösen, dass man den ErrorAction-Switch verwendet (siehe Abbildung 4) und die PowerShell-Engine anweist, das Script so zu behandeln, als ob die Variable ErrorActionPreference auf „Stop“ gesetzt wäre.
Parameter-Validierung
Funktionen sind nicht besonders nützlich, wenn sie keine Parameter akzeptieren können. Hilfsfunktionen sind eine andere Geschichte, obwohl unser Schwerpunkt auf regulären Funktionen liegt.
Daher ist die Parameter-Validierung ein sehr wichtiger Schritt, bevor wir beginnen, die gelieferten Parameter in unserer Programmierlogik zu verwenden.
Die PowerShell-Engine bietet eine Reihe von integrierten Mechanismen zur Validierung von Parametern. Erweiterte Funktionen können uns helfen, diese Funktionalität zur Validierung unserer Parameter zu nutzen, anstatt unsere eigene Parameter-Validierungslogik zu schreiben.
In diesem Abschnitt werden wir einige Parameter-Validierungstechniken besprechen. Diese Liste ist jedoch keineswegs erschöpfend.
1. Mandatory Parameter
Mandatory Parameter helfen dabei, bestimmte Parameter so zu deklarieren, wie sie von der Funktion benötigt werden. Wenn der Wert fehlt, fordert die PowerShell-Engine den Benutzer auf, einen Wert einzugeben (wie in Abbildung 5 dargestellt).
Hier ein Beispiel:
# Writing a function with a mandatory parameter Function Do-SomethingRegular { [CmdletBinding]()] Param( [Parameter(Mandatory)] [String] $Message ) Write-Output $Message } # Calling the function Do-SomethingRegular
2. ValidateScript
ValidateScript kann verwendet werden, um ein Script gegen den angegebenen Parameterwert auszuführen. Wenn das Script $true zurückgibt, dann wird der Parameterwert akzeptiert.
Hier ist ein Beispiel:
Function Simple-Function { [CmdletBinding()] param( [Parameter(Mandatory)] [ValidateScript({Test-Connection -ComputerName $_ -Quiet -Count 1})] [string]$computerName ) $ErrorActionPreference Get-CimInstance -ClassName win32_Process -ComputerName $ComputerName } Simple-Function -ComputerName 'CAT'
Wie wir in Abbildung 6 sehen können, verwenden wir ValidateScript, um zu testen, ob wir die vom Benutzer als ComputerName-Parameter angegebene Maschine erreichen können. Das Script verwendet das Cmdlet Test-Connection mit dem Flag „Quiet“, um entweder „true“ oder „false“ zurückzugeben.
Da unser Labor über keinen Computer mit dem Namen „CAT“ verfügt, gibt es „false“ zurück, und ValidateScript akzeptiert den Parameterwert nicht.
3. ValidatePattern
ValidatePattern kann verwendet werden, um einen Parameterwert gegen einen regulären Ausdruck zu validieren. Hier ein Beispiel:
Function Do-SomethingRegular {
[CmdletBinding()]
Param(
[Parameter(Mandatory)]
[ValidatePattern('\b((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(.|$)){4}\b')]
[String] $MachineName
)
Get-CimInstance -ComputerName $MachineName -ClassName win32_Process
}
Do-SomethingRegular -MachineName 127.0.01.1
Wie in Abbildung 7 gezeigt, validieren wir den gelieferten Wert des MachineName-Parameters gegen einen regulären Ausdruck für die IP-Adresse.4. ValidateSet
ValidateSet kann verwendet werden, um akzeptable Werte für einen Parameter vorzudefinieren (wie in Abbildung 8 gezeigt). Wenn der Benutzer andere als die vordefinierten Werte liefert, gibt die Funktion einen Fehler zurück. Hier ist ein Beispiel:
Function Do-SomethingRegular{ [CmdletBinding()] Param( [Parameter(Mandatory)] [ValidateSet('Mom','Dad')] [String] $Parent ) Write-Output "Hello " $Parent } Do-SomethingRegular -Parent
Wie bereits erwähnt, bietet PowerShell eine Reihe von Parameter-Validierungstechniken, dieser Blog-Post hat jedoch nur einige davon behandelt. Weitere Einzelheiten finden Sie im Artikel von Bruno Buyck über Parameter-Validierungskonzepte in PowerShell und ScriptRunner, eine vollständige Liste finden Sie in der offiziellen Microsoft PowerShell-Dokumentation.
Pipeline-Bindung
Parameter-Pipeline-Bindung ist eines der wichtigsten Konzepte in PowerShell. In diesem Abschnitt wird nur darauf eingegangen, wie Parameter für die Annahme von Pipeline-Eingaben aktiviert werden können. Weitere Einzelheiten finden Sie in meinem Artikel über Parameter-Bindungskonzepte in PowerShell.
Die PowerShell-Engine bindet die Pipeline-Eingabe nach Wert – „by Value“ – oder nach Eigenschaft – „by Property“. Mit erweiterten Funktionen können wir angeben, welche Parameter Pipeline-Eingaben akzeptieren können und wie die Bindung erfolgen soll.
Nehmen wir ein einfaches Beispiel, bei dem wir die Pipeline-Eingabe byValue akzeptieren:
Function Do-SomethingRegular{ [CmdletBinding()] Param( [Parameter(Mandatory,valueFromPipeline)] [String] $name ) Write-Output "You Entered $name" } "Sonny"|Do-SomethingRegular
Abbildung 9 zeigt, dass ein Zeichenkettenobjekt an unsere Funktion übergeben wird, und da die Funktion über einen Parameter verfügt, der den Wert aus der Pipeline akzeptiert, wird die Funktion ohne Fehler ausgeführt.
In ähnlicher Weise können wir unsere Funktion so ändern, dass sie die Pipeline-Eingabe byProperty akzeptiert:
Function Do-SomethingRegular{ [CmdletBinding()] Param( [Parameter(Mandatory,valueFromPipelineByProperty)] [String] $name ) Write-Output "You Entered $name" } $MyNewObject = [PSCustomObject]@{name = 'Sonny'; age = 21} $MyNewObject | Do-SomethingRegular
Wie in Abbildung 10 dargestellt, haben wir ein Objekt mit einem der Eigenschaft name erstellt, der dem Namen unseres Parameters entspricht.
Wenn dieses Objekt in der Pipeline übergeben wird, bindet die PowerShell-Engine die Eigenschaft mit den Parametern, da diese einen übereinstimmenden Namen haben.
Function Do-SomethingRegular{ [CmdletBinding()] Param( [Parameter(Mandatory,valueFromPipelineByPropertyName)] [String] $name ) process{ Write-Output "You Entered $name" } } $MyNewObject1 = [PSCustomObject]@{name = 'Sonny';age = 21} $MyNewObject2 = [PSCustomObject]@{name = 'browninfosecguy';age = 21} $MyNewObject1,$MyNewObject2|Do-SomethingRegular
Safeguards
PowerShell bietet zwei eingebaute Schutzmechanismen/Safeguards.
- WhatIf
- Confirm
Diese Schutzmechanismen werden durch zwei Systemvariablen gesteuert $WhatIfPreference und $ConfirmPreference. Der Standardwert dieser beiden Variablen ist in Abbildung 12 dargestellt.
WhatIf
Der WhatIf-Switch kann verwendet werden, um zu sehen, „was passiert wäre“, ohne wirklich etwas zu verändern. Sein Verhalten wird durch die $WhatIfPreference-Variable gesteuert.
Der Standardwert der $WhatIfPreference-Variable ist auf „false“ gesetzt, was der Grund dafür ist, dass uns beim Ausführen eines beliebigen Cmdlets kein „WhatIf“-Szenario angezeigt wird.
Um das WhatIf-Szenario anzuzeigen, müssen wir explizit den WhatIf-Switch verwenden, wie in Abbildung 13 dargestellt.
Die WhatIf-Funktionalität in einer Funktion kann folgendermaßen implementiert werden:
- Hinzufügen des SupportsShouldProcess-Arguments zu CmdletBinding, wie in Abbildung 14 gezeigt
- Erfassen des von $PSCmdlet.ShouldProcess(“”) zurückgegebenen booleschen Werts; wenn TRUE bedeutet dies, dass der Benutzer die WhatIf-Option nicht ausgewählt hat
- Platzieren der WhatIf-Logik in einer If-Schleife um $PSCmdlet.ShouldProcess(„“)
Das folgende Beispiel veranschaulicht diese Schritte:
Function Delete-Windows{ # First we're adding the “SupportsShouldProcess” argument to CmdletBinding [CmdletBinding(SupportsShouldProcess)] param( ) # Then, we're capturing the Boolean value returned by “$PSCmdlet.ShouldProcess("")”, If TRUE it means user has not selected whatif option if($PSCmdlet.ShouldProcess("Meow")){ Write-Host "WhatIf flag not set, delete windows" } else{ Write-Host "WhatIf flag set, do not delete windows or real" } }
Confirm
Der Confirm-Switch kann verwendet werden, um einen Benutzer vor dem Ausführen des Cmdlets zur Bestätigung aufzufordern. Wir können dasselbe in unserer Funktion implementieren. Wie bereits erwähnt, wenn die Variable $ConfirmPreference auf „High“ festgelegt ist, fordern die Cmdlets, bei denen die Variable ConfirmImpact auf „High“ festgelegt ist, den Benutzer vor der Ausführung des Cmdlets zur Bestätigung auf.
Dies bringt uns zu einem weiteren Konzept, der $ConfirmImpact-Variablen, die zur Definition des Schweregrads einer Funktion verwendet wird. Sie kann die folgenden Werte annehmen:
- „Low“
- „Medium“
- „High“
Wir können sie auch auf „None“ setzen, aber dann wird sie einfach deaktiviert.
Um confirm in unserer Funktion zu implementieren, müssen wir das ConfirmImpact-Argument zu CmdletBinding hinzufügen und einen Wert dafür initiieren. Das PowerShell-Modul vergleicht dann diesen Wert mit dem Wert von $ConfirmPreference, und wenn der Schweregrad unserer Funktion gleich oder höher ist, wird der Benutzer mit einem Confirm-Dialogfeld dazuaufgefordert, die Ausführung zu bestätigen. Hier ein Beispiel:
Function Delete-Windows{ [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Medium")] param( ) if($PSCmdlet.ShouldProcess("Meow"){ Write-Host "Delete Windows" } }
Wie wir in Abbildung 15 sehen können, hat das PowerShell-Modul den Benutzer nicht mit einem Dialog zur Bestätigung der Ausführung aufgefordert, da der Wert für $ConfirmPreference auf „High“ gesetzt ist und unsere Funktion einen „Medium“ ConfirmImpact hat.
Wenn wir den Wert von $ConfirmPreference auf „Medium“ ändern, wird der Benutzer wie in Abbildung 16 gezeigt per Dialogfeld zur Bestätigung der Ausführung aufgefordert.
Was geschieht nun, wenn wir die Variable $ConfirmPreference wieder auf „High“ zurücksetzen? Wie erwartet, werden wir, wenn wir nur „Delete-Windows“ ausführen, nicht per Dialogfeld zur Bestätigung aufgefordert; wenn wir jedoch explizit den Schalter „Confirm“ verwenden, wird uns das Dialogfeld angezeigt, wie in Abbildung 17 dargestellt.
Fazit
Der Wert erweiterter PowerShell-Funktionen ist klar ersichtlich. Sie reduzieren die unnötige Last der Implementierungslogik für die Parameter-Validierung, die Implementierung von Sicherheitsvorkehrungen und andere in diesem Blogbeitrag diskutierte Funktionen.
Wie immer, wenn Sie Fragen oder Bedenken haben, zögern Sie bitte nicht, uns zu kontaktieren.
Zusammenhängende Posts
9 min read
Scriptember 2024 – einen Monat lang feiern wir PowerShell und die begeisterten Menschen dahinter
Aug 16, 2024 by Heiko Brenn
Willkommen im Scriptember! Wir freuen uns, einen ganz besonderen Monat ankündigen zu können: Wir feiern einen Monat...
9 min read
Fünf Gründe für die Nutzung von PSReadLine
Aug 14, 2024 by Jeffery Hicks
Wie gut bist du mit dem Thema vertraut? Vielleicht gibt dir dieser Artikel nur einen Überblick. Aus meiner Erfahrung in...
14 min read
Privacy Management mit PowerShell – hier kommen die wichtigsten Funktionen von Priva auf einen Blick
Jul 16, 2024 by Damian Scoles
Kennst du Priva? Datenschutzmanagement, Datenschutzrichtlinien, Regeln und Subjektrechte-Anfragen (data subject rights...
Über den Autor:
Sonny ist ein selbsternannter PowerShell-Prediger, der in der schönen Stadt Halifax an der Ostküste Kanadas lebt. Sonny arbeitet seit mehr als 10 Jahren im Bereich Cybersecurity und hat als primärer technischer Leiter und Fachexperte bei vielen Cyber Security Assessments für verschiedene private und öffentliche Organisationen fungiert. Sonny spricht regelmäßig auf verschiedenen Sicherheitskonferenzen wie BSides, AtlSecCon, ISACA, OWASP etc.
Neueste Beiträge:
- Scriptember 2024 – einen Monat lang feiern wir PowerShell und die begeisterten Menschen dahinter
- Fünf Gründe für die Nutzung von PSReadLine
- Privacy Management mit PowerShell – hier kommen die wichtigsten Funktionen von Priva auf einen Blick
- Happy System Administrator Appreciation Day!
- PowerShell 7: Was spricht für, was gegen den Umstieg?