Was ist Windows PowerShell und was isst es? Teil 3: Übergeben von Parametern an Skripte und Funktionen, Erstellen von Cmdlets



Der zweite Teil der Serie befasste sich mit den Grundlagen der PowerShell-Programmiersprache. Jetzt lohnt es sich herauszufinden, wie der darauf geschriebene Code für Verwaltungsaufgaben verwendet werden kann. Der naheliegendste Weg, dies zu tun, besteht darin, das Skript auszuführen. Darüber hinaus können Sie eigene Cmdlets erstellen.

Inhaltsverzeichnis:


Positionsparameter
Param () -Block
Zusätzliche Parameterattribute
Übergeben von Parametern durch die Pipeline
Funktionskörperstruktur
Attribut [CmdletBinding ()] und erweiterte Funktionen Skriptmodule
und Erstellen von Cmdlets

Positionsparameter


In Skripten und Funktionen können Sie Positionsparameter (Argumente) übergeben, deren Werte in die integrierte Variable $ args geschrieben werden. Dieses eindimensionale Array erfordert keine vorherige Deklaration und sein Umfang ist auf ein Skript oder eine Funktion beschränkt. Führen Sie beispielsweise das einfachste Skript aus:

Write-Host " :" $args.count
Write-Host ":" $args


Bild

In Funktionen werden Positionsparameter auf die gleiche Weise verwendet:

function Print-Args {
    Write-Host " :" $args.count
    Write-Host " 0:" $args[0]
    Write-Host " 1:" $args[1] 
}

Print-Args “Zero” “One”

Bitte beachten Sie, dass beim Aufrufen von Print-Args kein Komma zwischen die Parameter gesetzt wird: Es handelt sich nicht um ein Array, das an die Funktion übergeben wird, sondern um einzelne Werte, die in das eindimensionale Array $ args geschrieben werden. Der Umfang wird durch den Funktionskörper begrenzt.

Bild

Mit der oben beschriebenen Methode können Sie eine beliebige Anzahl von Parametern an ein Skript oder eine Funktion übergeben. Beim Aufrufen müssen Sie jedoch die Reihenfolge ihrer Reihenfolge einhalten, und Sie können nur über den Index des Arrays darauf zugreifen. Dies ist nicht immer praktisch.

Param block ()


In Skripten und Funktionen ist es viel bequemer, benannte Parameter zu verwenden. In einem früheren Artikel haben wir über eine Möglichkeit gesprochen, sie zu beschreiben:

function test ($arg0, ..., $argN)
{
       
}

Eine ähnliche Syntax ist Entwicklern bekannt, aber wenn eine Funktion aufgerufen wird, werden die Parameter (falls vorhanden) durch Leerzeichen getrennt und nicht in Klammern eingeschlossen - es entsteht eine gewisse Dissonanz. Dies ist die Besonderheit von Shell-Sprachen: Für die Arbeit mit der Shell im interaktiven Modus sind Leerzeichen zwischen Werten viel praktischer. Der Testaufruf ($ value0) ist ebenfalls korrekt, aber der Parameter ist in diesem Fall der gesamte Ausdruck in Klammern, d. H. ($ value0) anstelle von $ value0 . Wenn Sie auf diese Weise mehrere Parameter übergeben, funktionieren diese nicht. Als Ergebnis des Aufrufs von test ($ value0, $ value1) erhält die Funktion nur eines - ein Array aus zwei Elementen mit den Werten $ value0 und $ value1 .

Die Microsoft Corporation empfiehlt die Verwendung des Param () -Blocks. Diese Syntax ist universeller und ermöglicht es Ihnen, nicht nur Funktionsargumente, sondern auch Skriptparameter anzugeben:

param (
    $arg0, $arg1
)

Write-Host $arg0 $arg1


Bild

Im Hauptteil der Funktion sieht es so aus:

function test {
     param (
           $arg0, $arg1
     )
}

Wenn die Argumentliste der Funktion klein ist, wird der Param () -Block nur das Design überladen, aber in vielen Fällen macht er den Code besser lesbar und ist unter anderem ein Element eines guten Programmierstils.

Zusätzliche Parameterattribute


Bei der Beschreibung von Funktionsargumenten oder Skriptparametern können deren zusätzliche Attribute festgelegt werden. Das einfachste Beispiel ist eine Zwangsinstallation des Typs:

param([int]$arg0)

oder

function test ([int]$arg0) {
}

Zusätzlich zum Typ Casting können Sie das Attribut [parameter ()] verwenden:

param(
    [parameter(Argument1=value1, Argument2=value2)]
    $ParameterName
)

Mit seiner Hilfe ist es einfach, den Parameter obligatorisch zu machen. Achten Sie auf die gleichzeitige Verwendung mehrerer Attribute - in diesem Fall folgen sie aufeinander:

param([parameter(Mandatory=$true)][int]$arg0)

oder

function test ([parameter(Mandatory=$true)][int]$arg0) { 
}

oder

function test {
          parameter([parameter(Mandatory=$true)][int]$arg0)
}


Bild

Mit Position können Sie die Reihenfolge des Parameters angeben (standardmäßig entspricht sie der Reihenfolge der Deklaration):

param(
                    [parameter(Mandatory=$true, Position=0)]
                    [int]
                    $arg0,

                    [parameter(Position=1)]
                    [string]
                    $arg1,

                    [parameter(Position=2)]
                    [array]
                    $arg2
)

Das Attribut [Parameter ()] enthält andere Argumente, von denen eine vollständige Liste auf der Microsoft- Website verfügbar ist . Dort werden andere Attribute beschrieben, mit deren Hilfe Sie die übergebenen Werte validieren, mit regulären Ausdrücken überprüfen usw. können. Hier einige Beispiele:

[Alias ​​()] legt einen Alias ​​für den Parameter fest:

param(
    [parameter(Mandatory=$true)]
    [alias("ARG","ArgumentName")]
    [string[]]
    $arg0
)

Der Umwandlungsoperator [string []] bedeutet, dass der Parameterwert ein String-Array ist.

[AllowNull ()] erlaubt $ null als erforderlichen Parameter:

param(
    [parameter(Mandatory=$true)]
    [AllowNull()]
    [string]
    $arg0
)

[AllowEmptyString ()] erlaubt eine leere Zeichenfolge als erforderlichen Parameter:

param(
    [parameter(Mandatory=$true)]
    [AllowEmptyString()]
    [string]
    $arg0
)

[AllowEmptyCollection ()] erlaubt ein leeres Array als erforderlichen Parameter:

param(
    [parameter(Mandatory=$true)]
    [AllowEmptyCollection()]
    [string[]]
    $arg0
)

[ValidatePattern ()] Validierung mit einem regulären Ausdruck:

param(
    [parameter(Mandatory=$true)]
    [ValidatePattern("[0-9][0-9][0-9][0-9]")]
    [string[]]
    $arg0
)

[ValidateLength ()] überprüft die Länge eines Zeichenfolgenparameters:

param(
    [parameter(Mandatory=$true)]
    [ValidateLength(1,10)]
    [string]
    $arg0
)

Parameter durch die Pipeline übergeben


Im ersten Artikel der Reihe haben wir über die Möglichkeit gesprochen, Daten über eine Pipeline an Cmdlets zu übertragen. In PowerShell geben Cmdlets und Funktionen Objekte oder Arrays von Objekten (Ergebnisse von Anweisungen) zurück und empfangen sie auch an der Eingabe. Um dies zu sehen, bereiten wir eines der Cmdlets mit Get-Help vor:

Get-Help Stop-Process -Parameter Name


Bild

Über die Pipeline können Sie Parameterwerte akzeptieren, für die die entsprechenden Attribute festgelegt sind (ByValue und / oder ByPropertyName). Im ersten Fall wird der Parameter mit einem über die Pipeline empfangenen Objekt abgeglichen, sofern sein Typ dem erwarteten entspricht. Im zweiten Parameter ist value die Eigenschaft des eingehenden Objekts, dessen Name dem Namen oder Alias ​​dieses Parameters entspricht. Verwenden Sie zum Festlegen der Attribute [parameter ()] mit den booleschen Argumenten ValueFromPipeline und ValueFromPipelineByPropertyName, deren Standardwert $ false ist:

param(
    [parameter(Mandatory=$true,
    ValueFromPipeline=$true)]
    [string[]]
    $Name
)

oder

param(
    [parameter(Mandatory=$true,
    ValueFromPipelineByPropertyName=$true)]
    [string[]]
    $Name
)

ValueFromPipelineByPropertyName wird normalerweise verwendet, wenn erforderlich, um mehrere Parameter zu übergeben, damit keine Verwirrung entsteht. Das Argument kann gleichzeitig mit ValueFromPipeline verwendet werden:

param(
    [parameter(Mandatory=$true,
    ValueFromPipeline=$true,
    ValueFromPipelineByPropertyName=$true)]
    [string[]]
    $Name
)

Write-Host $Name


Bild

Wie Sie sehen können, können Skripte auch Parameter über die Pipeline empfangen. Dennoch ist die praktische Anwendung der oben beschriebenen Attribute für erweiterte Funktionen wahrscheinlicher , auf die weiter unten eingegangen wird.

Funktionskörperstruktur


In PowerShell kann eine Funktion drei optionale Codeblöcke enthalten, die in Anweisungsklammern eingeschlossen sind - Begin, Process und End. Es sieht ungefähr so ​​aus:

function test
{
   param()
   begin {}
   process {}
   end {}
}

Der Begin-Block ist der erste, der einmal ausgeführt wird. Wenn die Parameter über die Pipeline an die Funktion übergeben werden, wird der Code ausgeführt, bevor das erste Objekt zur Verarbeitung eintrifft. Die Variablen $ _ und $ PSItem im Begin-Block enthalten in diesem Fall keine Werte. Wenn die Funktion mit explizit angegebenen Parametern aufgerufen wird, sind sie im Begin-Block verfügbar, da nicht auf den Empfang von Objekten aus der Pipeline gewartet werden muss. Als nächstes wird der Prozessblock ausgeführt: Wenn die Parameter durch die Pipeline geleitet werden, wird er für jedes Objekt einzeln gestartet. Bei explizit angegebenen Parametern startet der Prozessblock nur einmal. Die Funktion endet mit einer einmaligen Ausführung des Endblocks. Offensichtlich ist die Verwendung dieser Konstruktionen nur gerechtfertigt, wenn die Funktion Objekte aus der Pipeline empfangen kann:

function test
{

    param(
        [Parameter(ValueFromPipeline)]
        [string[]]
        $Param1,

        [string]$Param2
    )

    begin
    {
        Write-Host " Begin"
        Write-Host "       ( pipeline):" $Param1
        Write-Host "       ( ):" $Param2
    }

    process {
        Write-Host " Process"
        Write-Host "       ( pipeline):" $Param1
        Write-Host "       ( ):" $Param2
    }

    end
    {
        Write-Host " End"
        Write-Host "       ( pipeline):" $Param1
        Write-Host "       ( ):" $Param2
    }
}

'eins', 'zwei', 'drei' | test -Param2 'vier'

Bild

[CmdletBinding ()] Attribut- und erweiterte Funktionen


Verwenden Sie das Attribut [ CmdletBinding () ] , um "erweiterte" Funktionen (und streng genommen Skripte) zu erstellen . Insbesondere können Sie damit erweiterte Funktionen mit den Funktionen von in Visual Studio kompilierten binären Cmdlets definieren, bei denen es sich um Klassen von .NET Core-Klassen handelt. Da dieses Attribut hauptsächlich in Funktionen verwendet wird, werden wir bei ihnen aufhören:

function <Name>
{
    [CmdletBinding(ConfirmImpact=<String>,
    DefaultParameterSetName=<String>,
    HelpURI=<URI>,
    SupportsPaging=<Boolean>,
    SupportsShouldProcess=<Boolean>,
    PositionalBinding=<Boolean>)]

    Param ()

    Begin{}
    Process{}
    End{}
}

Tatsächlich initialisiert [CmdletBinding ()] eine neue Instanz der CmdletBindingAttribute- Klasse, indem ein Konstruktor aufgerufen wird, an den optionale Argumente übergeben werden können. Ihre detaillierte Beschreibung finden Sie auf der Microsoft- Website . Mit dem CmdletBinding-Attribut können Sie zusätzliche Funktionen der erweiterten Funktion steuern: Hinzufügen von Unterstützung für -Confirm und -WhatIf (über SupportsShouldProcess), -Force, -Verbose und -Debug sowie Deaktivieren der Positionsparameterbindung usw. Weiter werden wir die Verwendung spezieller Parameter analysieren.

Der Parameter -Force wird verwendet, um Anforderungen für verschiedene Operationen zu unterdrücken.

-Was, wennWird benötigt, um den Start zu emulieren und Informationen über die Folgen der Ausführung einer Funktion (eines Befehls) ohne diesen Parameter anzuzeigen. Wird häufig verwendet, wenn eine Funktion destruktive Aktionen ausführen kann.

Remove-Item C: \ Windows \ notepad.exe -WhatIf

Bild

-Confirm erfordert eine Bestätigung und wird auch verwendet, wenn die Funktion destruktive Aktionen ausführen kann.

function Delete-File {
[CmdletBinding(
    ConfirmImpact = 'High',
    SupportsShouldProcess = $true
)]
    param(
        [string]$File,
        [switch]$Force
    )
    if ($Force -or $PSCmdlet.ShouldProcess($File,"Delete file")) {
        Remove-Item $File
    }
}


Bild

Um -WhatIf und / oder -Confirm zu verarbeiten, wird die ShouldProcess-Methode (SupportsShouldProcess = $ true) aufgerufen, die die Ausführung des Befehls entweder auffordert oder emuliert. Um die Force-Verarbeitung zu implementieren, setzen wir sie zuerst in die IF-Bedingung. Zuerst wird der Ausdruck links vom Operator -or überprüft, und wenn er wahr ist, wird der Test gestoppt - die ShouldProcess-Methode wird nicht aufgerufen. Außerdem haben wir im Attribut [CmdletBinding ()] das ConfirmImpact-Argument angegeben, das den Einfluss des Codes auf das System bestimmt und den Parameterhandler -Confirm enthält. Dieses Argument kann die folgenden Werte annehmen:

Keine oder nicht angegeben - Bestätigungsmeldungen werden nicht angezeigt, selbst wenn der Parameter -Confirm übergeben wird.

Niedrig - Die Funktion wirkt sich geringfügig auf das System aus und birgt kein signifikantes Risiko für Datenverlust.

Mittlere - mittlere Exposition mit geringem Risiko eines Datenverlusts infolge destruktiver Maßnahmen.

Hoch - Der Code birgt ein hohes Risiko für Datenverlust aufgrund destruktiver Aktionen.

Standardmäßig wird für eine PowerShell-Sitzung die Belichtungsstufe als hoch angesehen. Der aktuelle Wert wird in der Variablen $ ConfirmPreference gespeichert. Wenn der Code die gleiche oder eine höhere Auswirkung auf das System hat, wird immer eine Bestätigungsanforderung angezeigt.

Optionen -Verbose und -Debugwird benötigt, um Debugging-Informationen anzuzeigen. Ihre Verwendung wird als guter Programmierstil angesehen (Write-Host vergessen, dies ist in erweiterten Funktionen nicht erforderlich). Der erste Parameter zeigt Informationen zum Fortschritt und der zweite detaillierte Debugging-Informationen an. Es ist auch möglich, auf die schrittweise Codeausführung umzuschalten. Das Verhalten von -Verbose und -Debug ist wie folgt definiert:

function Get-Something {
[CmdletBinding()]
    param()
    if ($PSBoundParameters.Verbose) {$VerbosePreference = "Continue"}
    if ($PSBoundParameters.Debug) {$DebugPreference = "Continue"}
    Write-Verbose "Type some verbose information"
    Write-Debug "Type some debug information"
}

Um mit speziellen Parametern zu arbeiten, haben wir die Variable $ PSBoundParameters verwendet. Standardmäßig sind die Werte von $ VerbosePreference und $ DebugPreference gleich 'SilentlyContinue'. Selbst wenn die entsprechenden Parameter angegeben werden, werden Debugging-Informationen nicht angezeigt - sie müssen in den Status 'Continue' übertragen werden.

Skriptmodule und Cmdlet-Erstellung


Beginnen wir mit der Erstellung eigener Cmdlets. In der Tat sind dies erweiterte Funktionen, die in der sogenannten beschrieben werden Skriptmodule - Textdateien mit der Erweiterung .psm1. Sie werden in Verzeichnissen gespeichert, die in der Umgebungsvariablen PSModulePath definiert sind. Sie können die Pfade zu ihnen mit dem folgenden Befehl

anzeigen : Get-ChildItem Env: \ PSModulePath | Format-Table -AutoSize

Der Standardsatz sieht ungefähr so aus:

C: \ Benutzer \% Benutzername% \ Dokumente \ WindowsPowerShell \ Module
C: \ Programme \ WindowsPowerShell \ Module
C: \ Windows \ System32 \ WindowsPowerShell \ v1.0 \ Module

Nachdem Sie die Datei ModuleName.psm1 mit der erweiterten Funktion "Datei löschen" aus dem vorherigen Abschnitt erstellt haben, müssen Sie sie beispielsweise in] C: \ Benutzer \% Benutzername% \ Dokumente \ WindowsPowerShell \ Module \ Modulname speichern. Bitte beachten Sie, dass das Skriptmodul in einem separaten Unterverzeichnis gespeichert werden muss, dessen Name mit dem Basisnamen (ohne Erweiterung) der .psm1-Datei übereinstimmt. Nach dem Ausführen des Befehls Import-Module ModuleName steht dem Benutzer die Funktion Delete-File zur Verfügung. Da sie erweitert ist, handelt es sich aus praktischer Sicht um dasselbe Cmdlet.

Bild

In diesem Artikel haben wir die Übergabe von Parametern an Funktionen und Skripte ausreichend detailliert untersucht. Der nächste Teil der Reihe konzentriert sich auf die objektorientierte Programmierung.

Teil 1: Windows PowerShell Essentials
2: Windows PowerShell
4: ,



All Articles