MAIN MENU
Devolutions Blog

Ankündigungen, Aktualisierungen und Einsichten von Devolutions

Devolutions PowerShell Universal dynamic forms illustration for the blog.

Dynamische Formulare mit dynamischen Parametern in PowerShell Universal erstellen

PowerShell Universal prüft DynamicParam und rendert adaptive Formulare. Fügen Sie ein Location-ValidateSet aus Division hinzu, zeigen Sie RunPipeline für Development und Azure DevOps und behalten Sie statische Parameter, wo möglich.

In diesem Beitrag zeigen wir, wie Sie dynamische Parameter in PowerShell Universal nutzen, um ein Formular bereitzustellen, das sich an die Eingabe des Benutzers anpasst.

Was sind dynamische Parameter?

Dynamische Parameter bieten eine Möglichkeit, einem Cmdlet oder einer erweiterten Funktion neue Parameter hinzuzufügen, basierend auf den bereits übergebenen Parametern. Wenn der Benutzer zum Beispiel angibt, dass der Wert eines Parameters -AuthenticationType Credential ist, können Sie anschließend einen Parameter -Credential zum Cmdlet hinzufügen. Das lässt sich oft besser mit Parametersätzen lösen, aber manchmal brauchen Sie etwas mehr Logik, um zu entscheiden, welche Parameter angezeigt werden.

Nachteile dynamischer Parameter sind typischerweise, dass sie weniger auffindbar sind als statische, weil sie erst zur Laufzeit auftauchen.

Unten sehen Sie ein Beispiel für dynamische Parameter in einem PowerShell-Skript. Dynamische Parameter erfordern, dass Sie jeden Aspekt des Parameters manuell definieren: Attribute, Typ und Name, und sie dann alle in ein Dictionary aufnehmen, das der DynamicParam-Block zurückgibt.

[CmdletBinding()]
param(
    [ValidateSet("Credential", "AppToken")]
    [string]$AuthenticationType
)

DynamicParam {
    $paramAttributes = [System.Management.Automation.ParameterAttribute]::new()
    $paramAttributes.Mandatory = $true
    $paramAttributesCollect = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $paramAttributesCollect.Add($paramAttributes)
    $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()

    if ($AuthenticationType -eq 'Credential') {
        $dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new("Credential", [PSCredential], $paramAttributesCollect)
        $paramDictionary.Add("Credential", $dynParam1)
    }

    if ($AuthenticationType -eq 'AppToken') {
        $dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new("AppToken", [SecureString], $paramAttributesCollect)
        $paramDictionary.Add("AppToken", $dynParam1)
    }

    return $paramDictionary
}

Dynamische Formulare in PowerShell Universal

PowerShell Universal kann Skripte prüfen, die dynamische Parameter definieren. So können Sie dynamische Formulare erstellen, die Ihre Benutzer nutzen. Sie merken nicht einmal, dass im Hintergrund PowerShell läuft.

In diesem Beispiel definieren wir ein Skript mit einem komplexeren dynamischen Parameteraufbau. Wir haben eine Auswahlliste für Division und System, und diese entscheiden, ob eine oder mehrere Komponenten anhand ihrer Werte angezeigt werden.

Zuerst definieren wir die statischen Parameter. Jeder ist eine Menge möglicher Werte in unserer fiktiven Organisation.

param(
    [ValidateSet("Sales", "HR", "Development")]
    [string]$Division,
    [ValidateSet("Entra ID", "Exchange", "Azure DevOps")]
    [string]$System
)

Als Nächstes definieren wir einen DynamicParam-Block und richten die Grundstruktur für dynamische Parameter ein.

DynamicParam {
    $paramAttributes = [System.Management.Automation.ParameterAttribute]::new()
    $paramAttributesCollect = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $paramAttributesCollect.Add($paramAttributes)
    $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
    return $paramDictionary
}

Das resultierende Skript zeigt ein Formular mit den zwei Dropdowns.

PowerShell Universal script form showing Division and System drop-downs.
Statische Parameter Division und System im Skriptformular

Zuerst fügen wir Logik hinzu, die festlegt, was passiert, wenn eine Division ausgewählt wird. In unserem fiktiven Unternehmen sind unsere Divisionen auf einige Standorte verteilt und zeigen ein weiteres Dropdown mit möglichen Werten für jede Division.

Anhand der ausgewählten Division entscheiden wir, welche Standorte verfügbar sind, und weisen ein ValidateSetAttribute zu, um mögliche Werte durchzusetzen.

$paramAttributes = [System.Management.Automation.ParameterAttribute]::new()
$paramAttributes.Mandatory = $true

if ($Division -eq 'Sales') {
    $validateAttribute = [System.Management.Automation.ValidateSetAttribute]::new("Washington DC", "Phoenix", "Chicago")
} elseif ($Division -eq 'HR') {
    $validateAttribute = [System.Management.Automation.ValidateSetAttribute]::new("London", "Seattle", "Orlando")
} elseif ($Division -eq 'Development') {
    $validateAttribute = [System.Management.Automation.ValidateSetAttribute]::new("Madison", "Boise", "Denver")
}

Anschließend können wir einen Parameter Location zu unserer Runtime-Parametersammlung hinzufügen.

$paramAttributesCollect = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
$paramAttributesCollect.Add($paramAttributes)
$paramAttributesCollect.Add($validateAttribute)

$dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new("Location", [string], $paramAttributesCollect)
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
$paramDictionary.Add("Location", $dynParam1)

Das Ergebnis: Unser Formular ändert die Werte des Standort-Dropdowns anhand der ausgewählten Division.

PowerShell Universal form showing a Location drop-down based on the selected division.
Location-Werte, die sich mit der ausgewählten Division ändern

Zum Schluss fügen wir weitere Logik hinzu, die sowohl den Divisions- als auch den Systemparameter prüft, um dem Formular einen weiteren Parameter hinzuzufügen. Wir können dasselbe Parameter-Dictionary verwenden und unseren neuen Parameter darin ergänzen. Dieser Parameter ist als boolescher Wert statt als Zeichenfolge definiert.

if ($Division -eq 'Development' -and $System -eq 'Azure DevOps') {
    $paramAttributes = [System.Management.Automation.ParameterAttribute]::new()
    $paramAttributesCollect = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $paramAttributesCollect.Add($paramAttributes)
    $dynParam2 = [System.Management.Automation.RuntimeDefinedParameter]::new("RunPipeline", [bool], $paramAttributesCollect)
    $paramDictionary.Add("RunPipeline", $dynParam2)
}

Das Ergebnis: Unser Formular passt sich jetzt Änderungen an den Divisions- und Systemparametern an.

PowerShell Universal form adding a RunPipeline field for Development and Azure DevOps.
RunPipeline erscheint für Development und Azure DevOps

Nachdem Sie die Parameter ins Skript eingegeben und es ausgeführt haben, sehen Sie, dass die dynamischen Parameterwerte zusammen mit den statischen übergeben werden.

PowerShell Universal job output showing static and dynamic parameter values together.
Statische und dynamische Parameterwerte in der Jobausgabe

Einschränkungen

Dynamische Parameter sind nützlich, aber in ihrem Umfang begrenzt. Das wird vor allem zum Problem, wenn Sie Parameter anhand des Werts der dynamischen Parameter selbst anpassen wollen. Sie könnten zum Beispiel in unserem Beispiel oben keine neuen dynamischen Parameter anhand von Location oder RunPipeline hinzufügen.

Dynamische Parameter können außerdem die Auffindbarkeit von Parametern in Funktionen wie dem Hilfesystem verringern und Ihre Funktionen schwerer verständlich machen. Definitionen dynamischer Parameter sind schwer zu lesen und für andere Entwickler in Ihrem Team möglicherweise schwer nachzuvollziehen.

Nutzen Sie nach Möglichkeit Parametersätze statt dynamischer Parameter. In PowerShell Universal können Sie auch Apps verwenden, um robustere Formulare zu definieren und Ihre Skripte bei statischen Parametern zu belassen.

Skript

Das vollständige Skript aus diesem Beitrag finden Sie unten.

param(
    [ValidateSet("Sales", "HR", "Development")]
    [string]$Division,
    [ValidateSet("Entra ID", "Exchange", "Azure DevOps")]
    [string]$System
)

DynamicParam {
    $paramAttributes = [System.Management.Automation.ParameterAttribute]::new()
    $paramAttributes.Mandatory = $true

    if ($Division -eq 'Sales') {
        $validateAttribute = [System.Management.Automation.ValidateSetAttribute]::new("Washington DC", "Phoenix", "Chicago")
    } elseif ($Division -eq 'HR') {
        $validateAttribute = [System.Management.Automation.ValidateSetAttribute]::new("London", "Seattle", "Orlando")
    } elseif ($Division -eq 'Development') {
        $validateAttribute = [System.Management.Automation.ValidateSetAttribute]::new("Madison", "Boise", "Denver")
    }

    $paramAttributesCollect = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $paramAttributesCollect.Add($paramAttributes)
    $paramAttributesCollect.Add($validateAttribute)

    $dynParam1 = [System.Management.Automation.RuntimeDefinedParameter]::new("Location", [string], $paramAttributesCollect)
    $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
    $paramDictionary.Add("Location", $dynParam1)

    if ($Division -eq 'Development' -and $System -eq 'Azure DevOps') {
        $paramAttributes = [System.Management.Automation.ParameterAttribute]::new()
        $paramAttributesCollect = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
        $paramAttributesCollect.Add($paramAttributes)
        $dynParam2 = [System.Management.Automation.RuntimeDefinedParameter]::new("RunPipeline", [bool], $paramAttributesCollect)
        $paramDictionary.Add("RunPipeline", $dynParam2)
    }

    return $paramDictionary
}

Bereit zum Bauen? PowerShell Universal herunterladen.