Created
May 6, 2016 18:29
-
-
Save torgro/65871d6594839c25c13a69f86982dda8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Get-NumberRange | |
{ | |
[cmdletbinding()] | |
Param() | |
DynamicParam { | |
$Dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary | |
$NewDynParam = @{ | |
Name = "Firstnumber" | |
Alias = "int" | |
Mandatory = $true | |
DPDictionary = $Dictionary | |
} | |
$NumberRange = @(1,2,3,4,5) | |
$null = $NewDynParam.Add("ValidateSet",$NumberRange) | |
if(-not (Get-Variable -Scope Global | Where-Object Name -eq "HiddenNumberVariable")) | |
{ | |
New-Variable -Name HiddenNumberVariable -Scope Global | |
} | |
# Create the Firstnumber parameter | |
New-DynamicParam @NewDynParam -Type int -ValidateScript {$null = Set-Variable -Name HiddenNumberVariable -Value $_ -Scope Global;$true} | |
$SecondNumberRange = @(1,2,3,4,5) | |
if(Get-Variable -Scope Global | Where-Object Name -eq "HiddenNumberVariable") | |
{ | |
$SecondNumberRange = $SecondNumberRange | Where-Object {$_ -gt (Get-Variable -Name HiddenNumberVariable -Scope Global).Value} | |
} | |
# Create the SecondNumber parameter | |
New-DynamicParam -Name SecondNumber -Type int -ValidateSet $SecondNumberRange -DPDictionary $Dictionary | |
#out-file -FilePath C:\temp\dynpara.txt -Encoding utf8 -InputObject (Get-Variable -Scope Global | where name -eq "HiddenNumberVariable" | out-string) | |
# Return the parameters | |
$Dictionary | |
Get-Variable -Name HiddenNumberVariable -Scope Global -ErrorAction SilentlyContinue | Remove-Variable -Scope Global | |
} | |
BEGIN{ | |
# Remove variable from the global scope, we don't need it anymore | |
Get-Variable -Name HiddenNumberVariable -Scope Global -ErrorAction SilentlyContinue | Remove-Variable -Scope Global | |
} | |
PROCESS{ | |
[pscustomobject]$PSBoundParameters | |
} | |
END{ | |
} | |
} | |
function New-DynamicParam | |
{ | |
<# | |
.SYNOPSIS | |
Helper function to simplify creating dynamic parameters | |
.DESCRIPTION | |
Helper function to simplify creating dynamic parameters | |
Example use cases: | |
Include parameters only if your environment dictates it | |
Include parameters depending on the value of a user-specified parameter | |
Provide tab completion and intellisense for parameters, depending on the environment | |
Please keep in mind that all dynamic parameters you create will not have corresponding variables created. | |
One of the examples illustrates a generic method for populating appropriate variables from dynamic parameters | |
Alternatively, manually reference $PSBoundParameters for the dynamic parameter value | |
.NOTES | |
Credit to http://jrich523.wordpress.com/2013/05/30/powershell-simple-way-to-add-dynamic-parameters-to-advanced-function/ | |
Added logic to make option set optional | |
Added logic to add RuntimeDefinedParameter to existing DPDictionary | |
Added a little comment based help | |
Credit to https://github.com/RamblingCookieMonster/PowerShell/blob/master/New-DynamicParam.ps1 | |
Credit to BM for alias and type parameters and their handling | |
.PARAMETER Name | |
Name of the dynamic parameter | |
.PARAMETER Type | |
Type for the dynamic parameter. Default is string | |
.PARAMETER Alias | |
If specified, one or more aliases to assign to the dynamic parameter | |
.PARAMETER ValidateSet | |
If specified, set the ValidateSet attribute of this dynamic parameter | |
.PARAMETER Mandatory | |
If specified, set the Mandatory attribute for this dynamic parameter | |
.PARAMETER ParameterSetName | |
If specified, set the ParameterSet attribute for this dynamic parameter | |
.PARAMETER Position | |
If specified, set the Position attribute for this dynamic parameter | |
.PARAMETER ValueFromPipelineByPropertyName | |
If specified, set the ValueFromPipelineByPropertyName attribute for this dynamic parameter | |
.PARAMETER HelpMessage | |
If specified, set the HelpMessage for this dynamic parameter | |
.PARAMETER DPDictionary | |
If specified, add resulting RuntimeDefinedParameter to an existing RuntimeDefinedParameterDictionary (appropriate for multiple dynamic parameters) | |
If not specified, create and return a RuntimeDefinedParameterDictionary (appropriate for a single dynamic parameter) | |
See final example for illustration | |
.EXAMPLE | |
function Show-Free | |
{ | |
[CmdletBinding()] | |
Param() | |
DynamicParam { | |
$options = @( gwmi win32_volume | %{$_.driveletter} | sort ) | |
New-DynamicParam -Name Drive -ValidateSet $options -Position 0 -Mandatory | |
} | |
begin{ | |
#have to manually populate | |
$drive = $PSBoundParameters.drive | |
} | |
process{ | |
$vol = gwmi win32_volume -Filter "driveletter='$drive'" | |
"{0:N2}% free on {1}" -f ($vol.Capacity / $vol.FreeSpace),$drive | |
} | |
} #Show-Free | |
Show-Free -Drive <tab> | |
# This example illustrates the use of New-DynamicParam to create a single dynamic parameter | |
# The Drive parameter ValidateSet populates with all available volumes on the computer for handy tab completion / intellisense | |
.EXAMPLE | |
# I found many cases where I needed to add more than one dynamic parameter | |
# The DPDictionary parameter lets you specify an existing dictionary | |
# The block of code in the Begin block loops through bound parameters and defines variables if they don't exist | |
Function Test-DynPar{ | |
[cmdletbinding()] | |
param( | |
[string[]]$x = $Null | |
) | |
DynamicParam | |
{ | |
#Create the RuntimeDefinedParameterDictionary | |
$Dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary | |
New-DynamicParam -Name AlwaysParam -ValidateSet @( gwmi win32_volume | %{$_.driveletter} | sort ) -DPDictionary $Dictionary | |
#Add dynamic parameters to $dictionary | |
if($x -eq 1) | |
{ | |
New-DynamicParam -Name X1Param1 -ValidateSet 1,2 -mandatory -DPDictionary $Dictionary | |
New-DynamicParam -Name X1Param2 -DPDictionary $Dictionary | |
New-DynamicParam -Name X3Param3 -DPDictionary $Dictionary -Type DateTime | |
} | |
else | |
{ | |
New-DynamicParam -Name OtherParam1 -Mandatory -DPDictionary $Dictionary | |
New-DynamicParam -Name OtherParam2 -DPDictionary $Dictionary | |
New-DynamicParam -Name OtherParam3 -DPDictionary $Dictionary -Type DateTime | |
} | |
#return RuntimeDefinedParameterDictionary | |
$Dictionary | |
} | |
Begin | |
{ | |
#This standard block of code loops through bound parameters... | |
#If no corresponding variable exists, one is created | |
#Get common parameters, pick out bound parameters not in that set | |
Function _temp { [cmdletbinding()] param() } | |
$BoundKeys = $PSBoundParameters.keys | Where-Object { (get-command _temp | select -ExpandProperty parameters).Keys -notcontains $_} | |
foreach($param in $BoundKeys) | |
{ | |
if (-not ( Get-Variable -name $param -scope 0 -ErrorAction SilentlyContinue ) ) | |
{ | |
New-Variable -Name $Param -Value $PSBoundParameters.$param | |
Write-Verbose "Adding variable for dynamic parameter '$param' with value '$($PSBoundParameters.$param)'" | |
} | |
} | |
#Appropriate variables should now be defined and accessible | |
Get-Variable -scope 0 | |
} | |
} | |
# This example illustrates the creation of many dynamic parameters using New-DynamicParam | |
# You must create a RuntimeDefinedParameterDictionary object ($dictionary here) | |
# To each New-DynamicParam call, add the -DPDictionary parameter pointing to this RuntimeDefinedParameterDictionary | |
# At the end of the DynamicParam block, return the RuntimeDefinedParameterDictionary | |
# Initialize all bound parameters using the provided block or similar code | |
.FUNCTIONALITY | |
PowerShell Language | |
#> | |
param( | |
[string]$Name | |
, | |
[System.Type]$Type = [string] | |
, | |
[string]$TypeAsString | |
, | |
[string[]]$Alias = @() | |
, | |
[string[]]$ValidateSet | |
, | |
[scriptblock]$validateScript | |
, | |
[switch]$Mandatory | |
, | |
[string]$ParameterSetName = "__AllParameterSets" | |
, | |
[int]$Position | |
, | |
[switch]$ValueFromPipelineByPropertyName | |
, | |
[switch]$ValueFromPipeline | |
, | |
[string]$HelpMessage | |
, | |
[validatescript({ | |
if(-not ( $_ -is [System.Management.Automation.RuntimeDefinedParameterDictionary] -or -not $_) ) | |
{ | |
Throw "DPDictionary must be a System.Management.Automation.RuntimeDefinedParameterDictionary object, or not exist" | |
} | |
$True | |
})] | |
$DPDictionary = $false | |
) | |
Add-Type @" | |
public class DynParamQuotedString { | |
public DynParamQuotedString(string quotedString) : this(quotedString, "'") {} | |
public DynParamQuotedString(string quotedString, string quoteCharacter) { | |
OriginalString = quotedString; | |
_quoteCharacter = quoteCharacter; | |
} | |
public string OriginalString { get; set; } | |
string _quoteCharacter; | |
public override string ToString() { | |
if (OriginalString.Contains(" ")) { | |
return string.Format("{1}{0}{1}", OriginalString, _quoteCharacter); | |
} | |
else { | |
return OriginalString; | |
} | |
} | |
} | |
"@ | |
if($PSBoundParameters.ContainsKey("TypeAsString")) | |
{ | |
$type = [System.Type]$TypeAsString | |
} | |
#Create attribute object, add attributes, add to collection | |
$ParamAttr = New-Object System.Management.Automation.ParameterAttribute | |
$ParamAttr.ParameterSetName = $ParameterSetName | |
if($mandatory) | |
{ | |
$ParamAttr.Mandatory = $True | |
} | |
if($Position -ne $null) | |
{ | |
$ParamAttr.Position=$Position | |
} | |
if($ValueFromPipelineByPropertyName) | |
{ | |
$ParamAttr.ValueFromPipelineByPropertyName = $True | |
} | |
if($ValueFromPipeline) | |
{ | |
$ParamAttr.ValueFromPipeline = $True | |
} | |
if($HelpMessage) | |
{ | |
$ParamAttr.HelpMessage = $HelpMessage | |
} | |
$AttributeCollection = New-Object 'Collections.ObjectModel.Collection[System.Attribute]' | |
$AttributeCollection.Add($ParamAttr) | |
#param validation set if specified | |
if($ValidateSet) | |
{ | |
$ParamOptions = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $ValidateSet | |
$AttributeCollection.Add($ParamOptions) | |
} | |
if($validateScript) | |
{ | |
$paramScript = New-Object -TypeName System.Management.Automation.ValidateScriptAttribute -ArgumentList $validateScript | |
$AttributeCollection.Add($paramScript) | |
} | |
#Aliases if specified | |
if($Alias.count -gt 0) { | |
$ParamAlias = New-Object System.Management.Automation.AliasAttribute -ArgumentList $Alias | |
$AttributeCollection.Add($ParamAlias) | |
} | |
#Create the dynamic parameter | |
$Parameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter -ArgumentList @($Name, $Type, $AttributeCollection) | |
#Add the dynamic parameter to an existing dynamic parameter dictionary, or create the dictionary and add it | |
if($DPDictionary) | |
{ | |
$DPDictionary.Add($Name, $Parameter) | |
} | |
else | |
{ | |
$Dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary | |
$Dictionary.Add($Name, $Parameter) | |
$Dictionary | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is awesome, thanks.