Created
May 18, 2018 17:33
-
-
Save rohnedwards/620e9f391b871e043f37657517b9ec2e to your computer and use it in GitHub Desktop.
Example of peeking into unbound parameters inside DynamicParam block. This is a bad idea, and should only be used for playing around with the PowerShell engine.
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
# Link to original question: https://powershell.org/forums/topic/retrieve-the-input-value-of-the-dynamic-parameter/ | |
function Test-DynamicParamCreation { | |
<# | |
.SYNOPSIS | |
Example of how to make dynamic param decisions based on other dynamic params. | |
NOTE: This probably isn't a good idea, as reflection is used to get at private | |
members of the PowerShell engine. | |
.DESCRIPTION | |
This function has a dynamic parameter named '-OtherDynamicParameterName' that | |
takes one or more parameter names (NOTE: Breaking this is pretty easy if you | |
don't pass single word strings) | |
The dynamic parameters created based on -OtherDynamicParameterName are very | |
simple, and are optional params that will accept any value. This functionality | |
isn't particulary useful, but is simply being used as a proof of concept to | |
show what's possible. | |
The function simply returns the $PSBoundParameters dictionary. | |
.EXAMPLE | |
Test-DynamicParamCreation -OtherDynamicParamName Test1, Test2 -Test1 test1 -Test2 test2 | |
This should return a dictionary with all three of those parameters. | |
.EXAMPLE | |
Test-DynamicParamCreation -OtherDynamicParamName Test1, Test2 -Test1 test1 -Test2 | |
This should result in an error since -Test2 had no value provied | |
.EXAMPLE | |
Test-DynamicParamCreation -OtherDynamicParamName Test1 -Test1 test1 -Test2 test2 | |
This should result in an error since -Test2 wasn't provided as a new dynamic parameter | |
to -OtherDynamicParamName | |
#> | |
[CmdletBinding()] | |
param( | |
) | |
DynamicParam { | |
$EC = $ExecutionContext.GetType().InvokeMember('_context', 'NonPublic, Instance, GetField', $null, $ExecutionContext, $null) | |
$CCP = $EC.GetType().InvokeMember('CurrentCommandProcessor', 'NonPublic, Instance, GetProperty', $null, $EC, $null) | |
$Binder = $CCP.GetType().InvokeMember('CmdletParameterBinderController', 'NonPublic, Instance, GetProperty', $null, $CCP, $null) | |
$ValidProperties = 'ParameterNameSpecified', 'ParameterName', 'ArgumentSpecified', 'ArgumentValue' | |
$UnboundArguments = $Binder.GetType().InvokeMember('UnboundArguments', 'NonPublic, Instance, GetProperty', $null, $Binder, $null) | ForEach-Object { | |
if (-not $ValidProperties) { | |
$ValidProperties = $_.GetType().GetProperties('NonPublic, Instance').Name | |
} | |
$Props = [ordered] @{} | |
foreach ($PropName in $ValidProperties) { | |
try { | |
$Props[$PropName] = $_.GetType().InvokeMember($PropName, 'NonPublic, Instance, GetProperty', $null, $_, $null) | |
} | |
catch {} | |
} | |
[PSCustomObject] $Props | |
} | |
$fakeBoundNamed = @{} | |
$fakeBoundUnNamed = New-Object System.Collections.ArrayList | |
$CurrentParamName = $null | |
foreach ($Arg in $UnboundArguments) { | |
if ($Arg.ParameterNameSpecified) { | |
if ($CurrentParamName) { | |
# Assume this is a switch | |
$fakeBoundNamed[$CurrentParamName] = $true | |
} | |
$CurrentParamName = $Arg.ParameterName | |
} | |
if ($Arg.ArgumentSpecified) { | |
if (-not $CurrentParamName) { | |
$fakeBoundUnNamed.Add($Arg.ArgumentValue) | Out-Null | |
} | |
else { | |
$fakeBoundNamed[$CurrentParamName] = $Arg.ArgumentValue | |
$CurrentParamName = $null | |
} | |
} | |
} | |
$ParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary | |
$ParamAttributes = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$ParamAttributes.Add((New-Object Parameter)) | |
$ParameterName = 'OtherDynamicParamName' | |
$ParamDictionary[$ParameterName] = New-Object System.Management.Automation.RuntimeDefinedParameter ( | |
$ParameterName, | |
[string[]], | |
$ParamAttributes | |
) | |
if ($NewParamNames = $fakeBoundNamed.$ParameterName) { | |
foreach ($NewParamName in ($NewParamNames -split '\s*\,\s*')) { | |
$NewParamAttributes = New-Object System.Collections.ObjectModel.Collection[System.Attribute] | |
$NewParamAttributes.Add((New-Object Parameter)) | |
$ParamDictionary[$NewParamName] = New-Object System.Management.Automation.RuntimeDefinedParameter ( | |
$NewParamName, | |
[object], | |
$NewParamAttributes | |
) | |
} | |
} | |
return $ParamDictionary | |
} | |
process { | |
$PSBoundParameters | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment