PowerShell 多个动态参数

问题描述 投票:0回答:2

我正在尝试为脚本模块创建一个函数,该函数在显示下一个参数之前验证前一个参数是否已设置。

我需要的参数是Identity、Share 和Quota。 我总是希望显示身份,在设置身份之前我不想显示共享,并且在设置共享之前我不想显示配额。

我能够轻松访问 $Identity,但无法从 DynamicParam{} 中访问 $Share。 我使用 PowerGUI 单步执行脚本,当我点击 Begin{} 时我只能看到 $Share。

如果设置了身份,我有一种方法可以通过仅显示共享/配额来解决此问题,但最终我想了解如何根据先前设置的参数继续添加其他参数。

该函数的副本如下。 personfileutility.exe 只是我们用来与各种系统交互以配置和收集用户信息的可执行文件。

function New-PersonalFiles
{
    [CmdletBinding()]
    Param
    (
        # Param1 help description
        [Parameter(Mandatory=$true)]
        $Identity
    )

    DynamicParam
        {
            $paramDictionary = new-object -Type System.Management.Automation.RuntimeDefinedParameterDictionary

            if (($Identity -notlike "") -or ($Identity -notlike $null)){
                $attributes = new-object System.Management.Automation.ParameterAttribute
                $attributes.ParameterSetName = "__AllParameterSets"
                $attributes.Mandatory = $true

                $lookup = [xml](\\servername\personalfiles\personfileutility.exe -a $Identity)

                $type = $lookup.User.user_directory.type.type

                if ($type -like "other" -or $type -like "staff") {
                    $arguments = @()
                    $arguments += "\\fileserver\sharename"
                }
                elseif ($type -like "faculty") {
                    $arguments = @()
                    $arguments += "\\fileserver\sharename"
                    $arguments += "\\fileserver\sharename2"

                }
                elseif ($type -like "student") {
                    $arguments = @()
                    $arguments += "\\fileserver2\sharename"
                }

                $ParamOptions = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $arguments

                $attributeCollection = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
                $attributeCollection.Add($attributes)
                $attributeCollection.Add($ParamOptions)


                $dynParam1 = new-object -Type System.Management.Automation.RuntimeDefinedParameter("Share", [String], $attributeCollection)

                $paramDictionary.Add("Share", $dynParam1)
            }

            if (($Share -like "\\fileserver\*"))
            {
                $attributes2 = new-object System.Management.Automation.ParameterAttribute
                $attributes2.ParameterSetName = "__AllParameterSets"
                $attributes2.Mandatory = $true

                $lookup = [xml](\\servername\personalfiles\personfileutility.exe -a $Identity)

                $type = $lookup.User.user_directory.type.type

                if ($type -like "other" -or $type -like "staff") {
                    $arguments = @()
                    $arguments += "15GB"
                    $arguments += "20GB"
                }
                elseif ($type -like "faculty") {
                    $arguments = @()
                    $arguments += "10GB"
                    $arguments += "15GB"

                }
                elseif ($type -like "student") {
                    $arguments = @()
                    $arguments += "5GB"
                    $arguments += "10GB"
                }

                $ParamOptions2 = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $arguments2

                $attributeCollection2 = new-object -Type System.Collections.ObjectModel.Collection[System.Attribute]
                $attributeCollection2.Add($attributes2)
                $attributeCollection2.Add($ParamOptions2)


                $dynParam2 = new-object -Type System.Management.Automation.RuntimeDefinedParameter("Quota", [String], $attributeCollection2)

                $paramDictionary.Add("Quota", $dynParam2)
            }

            return $paramDictionary
        }

    <#
    .Synopsis
       Short description
    .DESCRIPTION
       Long description
    .EXAMPLE
       Example of how to use this cmdlet
    .EXAMPLE
       Another example of how to use this cmdlet
    #>

    Begin
    {
    }
    Process
    {
        \\servername\personalfiles\personfileutility.exe -a $Identity -c -q ((Invoke-Expression $PSBoundParameters.Quota)  / 1KB) -s $Share
    }
    End
    {
    }
}
powershell dynamic powershell-3.0
2个回答
3
投票

我正在尝试复制您正在使用的“解决方法”,但我只看到我可以访问动态参数

Share
(而不是
Quota
)。为了重现您的设置,由于我无法访问 personfileutility.exe,我注释掉了两行并添加了第三行,其中我将
$type
硬编码为“faculty”。例如,在两个地方我将代码更新为:

#$lookup = [xml](\\servername\personalfiles\personfileutility.exe -a $Identity)
#$type = $lookup.User.user_directory.type.type
$type = "faculty"

完成这些更改后,我可以在指定

Share
后访问
Identity
参数。 但是,我无法访问
Quota
。您期望
Quota
可用吗?

如果我理解您所问的问题,那么您不希望

Share
可以访问,直到
Identity
可以访问(您目前正在工作)。但除此之外,您不希望
Quota
可供访问,直到
Identity
Share
都已填写,并且您不知道如何实现该功能。这是正确的吗?

如果我正确理解了这个问题,我不相信 PowerShell 提供了一种通过 Commandlet 绑定来实现这一目标的机制。我认为您可以通过使用 GUI 应用程序或交互式提示用户输入来实现此目的。


0
投票

大家好消息!我自己也面临这样的问题,不知道该怎么办。我搜索了几个论坛但没有找到。

但好消息是:它可以在 PowerShell 中运行。您可以根据值(而不是参数本身)定义多个动态参数。您只需退后两步并重新思考实际问题是什么。

所以我的函数有三个参数:TeamChannelMessageTeam 参数是第一个参数,直接在函数中声明。 ChannelMessage 参数是在运行时添加到函数的动态参数。

Team参数仅接受可以使用 [TAB] 完成的预定义值(来自哈希表)。只有设置了这个值,函数才会添加第二个参数Channel,它也只接受有效值(也可以用[TAB]完成)。最后,如果第二个参数也有有效值,则将第三个参数Message添加到函数中。

参数列表理论上可以永远持续下去,但三个对我来说就足够了:-)所以这里是代码:

$hashtable = @{
    "Team 1" = @{
        "Channel T1-1" = "123"
        "Channel T1-2" = "456"
        "Channel T1-3" = "789"
    }
    "Team 2" = @{
        "Channel T2-1" = "123"
        "Channel T2-2" = "456"
    }
    "Team 3" = @{
        "Channel T3-1" = "123"
        "Channel T3-2" = "456"
    }
}


function Send-MessageToMSTeams
{
    [CmdletBinding()]
    param
    (
        [Parameter(Mandatory = $true)]
        [string]$Team
    )

    dynamicparam
    {
        $paramDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary

        if ($PSBoundParameters.ContainsKey('Team') -and $MSTeamsWebhooks.ContainsKey($PSBoundParameters['Team']))
        {
            $selectedTeam = $PSBoundParameters['Team']
            $teamChannels = $MSTeamsWebhooks[$selectedTeam].Keys
            $channelAttribute = New-Object -TypeName System.Management.Automation.ParameterAttribute
            $channelAttribute.Mandatory = $true
            $channelParameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter('Channel', [string], $channelAttribute)
            $channelParameter.Attributes.Add((New-Object System.Management.Automation.ValidateSetAttribute($teamChannels)))
            $paramDictionary.Add('Channel', $channelParameter)
        }

        if ($paramDictionary.ContainsKey('Channel'))
        {
            $messageAttr = New-Object -TypeName System.Management.Automation.ParameterAttribute
            $messageAttr.Mandatory = $true
            $messageParam = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter('Message', [string], $messageAttr)
            $paramDictionary.Add('Message', $messageParam)
        }

        return $paramDictionary
    }

    process
    {
        Write-Host $PSBoundParameters
    }
}

因此,诀窍是不要使用

$PSBoundParameters
或参数名称本身(就像您在代码中使用
$Share
所做的那样),而是在之前将其添加到 if 块中时使用
$paramDictionary

祝你好运!

© www.soinside.com 2019 - 2024. All rights reserved.