我尝试将System.ComponentModel.DefaultValueAttribute添加到RuntimeDefinedParameter的AttributeCollection中,但它不起作用..
答案 0 :(得分:2)
正如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。
答案 1 :(得分:2)
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
}
答案 2 :(得分:1)
System.Management.Automation.RuntimeDefinedParameter具有'Value'属性,所以我想我会用它来设置默认值。它有点工作(当我调试脚本我可以使用$ PSCmdlet.GetDynamicParameters()看到这个'默认'值)但我没有运气在实际函数中访问它(它的执行'死'在$ pscmdlet.GetDynamicParameters()调用)
无论如何:当我指定值时,我的函数显示的是绑定值而不是默认值。
不确定是否有帮助,TBH在参数动态时几乎看不到任何默认值的用例。很想知道你为什么需要它。 :)
答案 3 :(得分:1)
这不完全是您所需要的,但至少是一个很好的解决方法(需要PowerShell 3.0):
您可以使用$PSDefaultParameterValues
为所有功能的所有参数设置默认值。请参阅https://technet.microsoft.com/en-us/library/hh847819.aspx或使用about_Parameters_Default_Values
上的PowerShell帮助。
答案 4 :(得分:0)
好的,因此回答问题的每个人都正确地设置了动态参数的“默认”值。 (剧透警报/ tl; dr:没有这样的东西。)现在,让我在开头说我要演示的功能是通过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
$RequestTimeoutParameter.Value = $(if ($PSBoundParameters.UseDynamicParameterDefault1) { 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')) {
Write-Host "`$RequestTimeout = $RequestTimeout (Bound)"
} else {
Write-Host "`$RequestTimeout = $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 {
Write-Host "`$RequestTimeout = $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
Value : 120000
IsSet : True
Attributes : {__AllAttributes, 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
$RequestTimeout = 3000 (Bound)
PS C:\>
好的,因此我从此输出中学到了一些东西。一种是我在构造动态参数时试图使用$PSBoundParameters
来设置其默认值(为2000或120000)。但是,这不起作用,因为尚未处理参数。发生的情况是创建了参数,然后绑定了发送到cmdlet的各种参数的值。如果指定了动态参数的值,则会更新动态参数的Value
属性。因此,从这个意义上说,Value
属性不是动态参数的默认值,而不是;它是参数的 值。
因此,在我尝试根据其他(绑定)参数的值设置动态参数的“默认”值的函数中,此方法不起作用,并且值120000
始终设置为动态参数的初始值。
好的,但是当我没有为cmdlet的调用指定-RequestTimeout <n>
时,在cmdlet中引用$RequestTimeout
会导致返回空值。是什么赋予了?如何获得我在参数上设置的默认值?这很容易。我仍然可以访问用于建立参数定义的$RequestTimeoutParameter
变量。正如您在输出中看到的那样,我将其写了出来,您可以看到Value
属性已设置。此外,如果指定了-RequestTimeout <n>
,则$RequestTimeoutParameter.Value
属性将使用命令调用中传递的值进行更新。
我希望这可以帮助其他人。
答案 5 :(得分:0)
为什么不检查用户是否指定了参数,如果不是,则在begin-block中提供该参数的值;
function Get-Something {
param()
dynamicparam{
<Definition of dynamic parameter "ThisIsADynamicParam">
}
begin {
if (-not $PSBoundParameters.ContainsKey('ThisIsADynamicParam') {
$PSBoundParameters.Add('ThisIsADynamicParam','DefaultValue')
}
}
}
答案 6 :(得分:0)
这可能很明显,但是我还没有看到有人具体提及此事,但是如果您将“四点半”的出色解释,克里斯西的初步答案以及托马斯的巧妙建议结合在一起,就可以了。
您可以将动态参数的值(根据用户提供的输入而变化)动态分配给$ 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上进行了测试