5

我尝试将 System.ComponentModel.DefaultValueAttribute 添加到 RuntimeDefinedParameter 的 AttributeCollection,但它不起作用..

4

7 回答 7

4

Chrissy 的示例可能是正确的方法,但我无法检索默认值。指定默认值时,$PSBoundParameters 中不存在该参数。

我们应用的“解决方法”是将 $PSBoundParameter["Background"] 绑定到我们想要的默认值。$PSBoundParameters["Background"] = "Transparent"

扩展 Chrissy 的示例:

DynamicParam  {
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    $colorlist = [System.Enum]::GetNames([System.Drawing.KnownColor])

    $attributes = New-Object System.Management.Automation.ParameterAttribute
    $attributes.ParameterSetName = "__AllParameterSets"
    $attributes.Mandatory = $false

    # Background color
    $validationset = New-Object -Type System.Management.Automation.ValidateSetAttribute -ArgumentList $colorlist
    $collection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $collection.Add($attributes)
    $collection.Add($validationset)
    $background = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("Background", [String], $collection)
    $PSBoundParameters["Background"] = "Transparent"

    $newparams = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
    $newparams.Add("Background", $background)

    return $newparams
}
于 2016-12-22T14:40:51.180 回答
3

正如 Bartek 建议的那样,可以使用 Value 属性,如下面的代码所示

DynamicParam  {
    [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    $colorlist = [System.Enum]::GetNames([System.Drawing.KnownColor])

    $attributes = New-Object System.Management.Automation.ParameterAttribute
    $attributes.ParameterSetName = "__AllParameterSets"
    $attributes.Mandatory = $false

    # Background color
    $validationset = New-Object -Type System.Management.Automation.ValidateSetAttribute -ArgumentList $colorlist
    $collection = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute]
    $collection.Add($attributes)
    $collection.Add($validationset)
    $background = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("Background", [String], $collection)
    $background.Value = "Transparent"

    $newparams = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
    $newparams.Add("Background", $background)

return $newparams
}

这里重要的一行是 $background.Value = "Transparent" 其中 $background 是一个 RunTimeDefinedParameter。

对于那些好奇的人。我最初尝试将其用作属性,但 ParameterAttributes 中没有可用的 .Value。

于 2015-09-14T14:52:06.563 回答
1

System.Management.Automation.RuntimeDefinedParameter 具有“值”属性,所以我想我会用它来设置默认值。它有点工作(当我调试脚本时,我可以使用 $PSCmdlet.GetDynamicParameters() 看到这个“默认”值)但我没有运气在实际函数中访问它(它在 $pscmdlet.GetDynamicParameters() 调用上“死”了) .

无论如何:当我指定值时,我的函数显示的是绑定值而不是默认值。

不确定它是否有帮助,而且当参数是动态的时,我几乎看不到任何默认值的用例。很想知道你为什么需要它。:)

于 2012-06-13T11:28:28.990 回答
1

它不完全是您所需要的,但至少是一个很好的解决方法(需要 PowerShell 3.0):

您可以使用 为所有函数的所有参数设置默认值$PSDefaultParameterValues。请参阅https://technet.microsoft.com/en-us/library/hh847819.aspx或使用 PowerShell 帮助about_Parameters_Default_Values

于 2015-03-24T13:04:40.133 回答
1

更新:
我在我的 PowerShell 函数中发现了一个错误Test-DynamicParameter,这导致了一个错误的结论。下面,在 PowerShell 函数中,我将注释掉错误的行。此外,最后一个示例输出已更改。再次,我将注释更改。

好的,所以回答的每个人在如何设置动态参数的“默认”值方面都是正确的。(剧透警报/tl;博士:没有这样的事情。)现在,让我先说我即将演示的功能是通过 PowerShell 5.1 执行的。以下是我在测试中发现的。

首先,我用来测试动态参数和默认值的函数:


function Test-DynamicParameter {
    [CmdletBinding()]
    Param (
        [switch]$UseDynamicParameterDefault2000
    )

    dynamicparam {
        # $RequestTimeout parameter
        $attributeCollection = New-Object Collections.ObjectModel.Collection[Attribute]
        $attributeCollection.Add((New-Object Management.Automation.ParameterAttribute -Property @{ ParameterSetName = "__AllParameterSets" }))
        $attributeCollection.Add((New-Object Management.Automation.ValidateScriptAttribute { $_ -ge 0 }))

        $RequestTimeoutParameter = New-Object Management.Automation.RuntimeDefinedParameter RequestTimeout, int, $attributeCollection
        # This line uses an incorrect name for the dynamic parameter, which caused
        # incorrect results in my original post. The corrected line
        # appears below this commented out, incorrect line.
        #$RequestTimeoutParameter.Value = $(if ($PSBoundParameters.UseDynamicParameterDefault1) { 2000 } else { 120000 })
        $RequestTimeoutParameter.Value = $(if ($PSBoundParameters.UseDynamicParameterDefault2000) { 2000 } else { 120000 })

        $dynamicParams = New-Object Management.Automation.RuntimeDefinedParameterDictionary
        $dynamicParams.Add('RequestTimeout', $RequestTimeOutParameter)

        $dynamicParams
    }

    process {
        $RequestTimeoutParameter | Format-List

        if ($PSBoundParameters.ContainsKey('UseDynamicParameterDefault2000')) {
            Write-Host "`$PSBoundParameters contains 'RequestTimeout'? $($PSBoundParameters.ContainsKey('RequestTimeout'))"
            Write-Host "`$RequestTimeout default: 2000"
            if ($PSBoundParameters.ContainsKey('RequestTimeout')) {
                # UPDATE: The following line should have used $PSBoundParameters to access the RequestTimeout parameter and has been corrected below
                #Write-Host "`$RequestTimeout = $RequestTimeout (Bound)"
                Write-Host "`$RequestTimeout = $($PSBoundParameters['RequestTimeout']) (Bound)"
            } else {
                # UPDATE: To be safe, also access $RequestTimeout here via $PSBoundParameters
                #Write-Host "`$RequestTimeout = $RequestTimeout (Default Value)"
                Write-Host "`$RequestTimeout = $($PSBoundParameters['RequestTimeout']) (Default Value)"
            }
        } else {
            Write-Host "`$PSBoundParameters contains 'RequestTimeout'? $($PSBoundParameters.ContainsKey('RequestTimeout'))"
            Write-Host "`$RequestTimeout default: 120000"
            if ($PSBoundParameters.ContainsKey('RequestTimeout')) {
                Write-Host "`$RequestTimeout = $($PSBoundParameters['RequestTimeout']) (Bound)"
            } else {
                # UPDATE: Again, use $PSBoundParameters
                #Write-Host "`$RequestTimeout = $RequestTimeout (UnBound, Default Value)"
                Write-Host "`$RequestTimeout = $($PSBoundParameters['RequestTimeout']) (UnBound, Default Value)"
            }
        }
    }
}

现在执行该函数的一些测试(同样,使用 PowerShell 5.1):

PS C:\> Test-DynamicParameter


Name          : RequestTimeout
ParameterType : System.Int32
Value         : 120000
IsSet         : True
Attributes    : {__AllParameterSets, System.Management.Automation.ValidateScriptAttribute}



$PSBoundParameters contains 'RequestTimeout'? False
$RequestTimeout default: 120000
$RequestTimeout =  (Unbound, Default Value)

PS C:\> Test-DynamicParameter -RequestTimeout 3000


Name          : RequestTimeout
ParameterType : System.Int32
Value         : 3000
IsSet         : True
Attributes    : {__AllParameterSets, System.Management.Automation.ValidateScriptAttribute}



$PSBoundParameters contains 'RequestTimeout'? True
$RequestTimeout default: 120000
$RequestTimeout = 3000 (Bound)

PS C:\> Test-DynamicParameter -UseDynamicParameterDefault2000

Name          : RequestTimeout
ParameterType : System.Int32
### UPDATE: Due to incorrect code, this line was wrong...
### Value         : 120000
Value         : 2000
IsSet         : True
Attributes    : {__AllParameterSets, System.Management.Automation.ValidateScriptAttribute}



$PSBoundParameters contains 'RequestTimeout'? False
$RequestTimeout default: 2000
$RequestTimeout =  (Default Value)

PS C:\> Test-DynamicParameter -UseDynamicParameterDefault2000 -RequestTimeout 3000


Name          : RequestTimeout
ParameterType : System.Int32
Value         : 3000
IsSet         : True
Attributes    : {__AllParameterSets, System.Management.Automation.ValidateScriptAttribute}



$PSBoundParameters contains 'RequestTimeout'? True
$RequestTimeout default: 2000
### UPDATE: This line is incorrect when the PowerShell function is corrected.
### $RequestTimeout = 3000 (Bound)
###
$RequestTimeout = 3000 (Bound)

PS C:\>

好的,所以我从这个输出中学到了一些东西。一个是我在构造动态参数时尝试使用$PSBoundParameters它来设置其默认值(为 2000 或 120000)。但是,这不起作用,因为尚未处理参数。 (我错了,你可以$PSBoundParameters在构造动态参数时使用。)发生的情况是创建了参数,然后绑定了发送到 cmdlet 中的各种参数的值。在指定动态参数的值的情况下,动态参数的Value属性被更新。那么,从这个意义上说,该Value属性不是动态参数的默认值;它是参数值。

因此,在我尝试根据其他(绑定)参数的值设置动态参数的“默认”值的函数中,这不起作用,并且该值120000始终设置为动态参数的初始值。 (由于我的编码错误,这是真的。但是一旦更正了代码,这个陈述就是错误的。)

好的,但是当我没有指定-RequestTimeout <n>cmdlet 的调用时,在 cmdlet 中引用会$RequestTimeout导致 null 值。是什么赋予了?如何获得我在参数上设置的默认值?这很容易。我仍然可以访问$RequestTimeoutParameter用于构建参数定义的变量。正如您在输出中看到的那样,我将其写出来,您可以看到Value属性已设置。此外,如果-RequestTimeout <n>指定,则$RequestTimeoutParameter.Value使用从命令调用传入的值更新属性。

我希望这对其他人有帮助。

于 2019-07-17T21:07:34.907 回答
0

为什么不检查参数是否由用户指定,如果不是,例如在开始块中为参数提供一个值;

function Get-Something {
    param()
    dynamicparam{
        <Definition of dynamic parameter "ThisIsADynamicParam">
    }
    begin {
        if (-not $PSBoundParameters.ContainsKey('ThisIsADynamicParam') {
            $PSBoundParameters.Add('ThisIsADynamicParam','DefaultValue')
        }

    }
}
于 2019-12-19T14:12:38.180 回答
0

这可能很明显,但我还没有看到有人特别提到这一点,但如果你结合了fourpastmidnights 的出色解释、chrissy 的初步回答和 Tomas 的聪明建议。

可以将根据用户提供的输入更改的动态参数的值动态分配给 $PSBoundParameter 字典,从而实现在未指定任何内容时提供可访问的默认值的预期效果,同时在用户输入的事件中更新它假如。

    dynamicParam {
    if ($Param1 -eq $True) {
        #Create Abstract Object
        $paramDictionary = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameterDictionary
        $attributeCollection = New-Object -TypeName System.Collections.ObjectModel.Collection[System.Attribute]

        #Define Param attributes
        $attribute = New-Object System.Management.Automation.ParameterAttribute
        $attribute.Mandatory = $false
        $attributeCollection.Add($attribute)

        #Create Param
        $Name = 'DynamicParam1'
        $dynParam = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter($Name, [bool], $attributeCollection)
        $dynParam.value = $true
        $paramDictionary.Add($Name, $dynParam)
        $PSBoundParameters["$name"] = $dynParam.Value
    }
    $paramDictionary
}

因此,此示例将允许您访问$PSBoundParameters.DynamicParam1默认值$true或用户提供的值(如果提供了值)的值。

据我所知,该行$PSBoundParameters["$name"] = $dynParam.Value必须在“默认”赋值语句之后$dynParam.value = $true

这是在 PS 7.1 上测试的

于 2020-10-08T14:27:25.440 回答