New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ProxyCommand]::Create doesn't generate dynamic param block for function that has dynamic parameters #4792
Comments
Any suggested way to workaround this issue? Thanks. |
Many years ago I used the following code in a proxy for dynamicparam
{
$argList = @($psboundparameters.getenumerator() | % { "-$($_.Key)"; $_.Value })
$wrappedCmd = Get-Command Get-ChildItem -Type Cmdlet -ArgumentList $argList
$providerParams = @($wrappedCmd.Parameters.GetEnumerator() | Where-Object { $_.Value.IsDynamic })
if ($providerParams.Length -gt 0)
{
$paramDictionary = new-object System.Management.Automation.RuntimeDefinedParameterDictionary
foreach ($param in $providerParams)
{
$param = $param.Value
$dynParam1 = new-object System.Management.Automation.RuntimeDefinedParameter $param.Name, $param.ParameterType, $param.Attributes
$paramDictionary.Add($param.Name, $dynParam1)
}
return $paramDictionary
}
} Worth noting - this takes the current arguments and passes them to There are problems with how |
Worth adding that including dynamic parameters is the default behavior for compiled cmdlets, and therefore also should be for (advanced) functions and scripts (which are equally affected). @IISResetMe has found a workaround via This method automatically generates code similar to @lzybkr's above; running try {
$targetCmd = $ExecutionContext.InvokeCommand.GetCommand('ProxyTest', [System.Management.Automation.CommandTypes]::Function, $PSBoundParameters)
$dynamicParams = @($targetCmd.Parameters.GetEnumerator() | Microsoft.PowerShell.Core\Where-Object { $_.Value.IsDynamic })
if ($dynamicParams.Length -gt 0)
{
$paramDictionary = [Management.Automation.RuntimeDefinedParameterDictionary]::new()
foreach ($param in $dynamicParams)
{
$param = $param.Value
if(-not $MyInvocation.MyCommand.Parameters.ContainsKey($param.Name))
{
$dynParam = [Management.Automation.RuntimeDefinedParameter]::new($param.Name, $param.ParameterType, $param.Attributes)
$paramDictionary.Add($param.Name, $dynParam)
}
}
return $paramDictionary
}
} catch {
throw
} |
I am getting the expected output on PS 7.2+, marking as resolved. |
This issue has been marked as fixed and has not had any activity for 1 day. It has been closed for housekeeping purposes. |
@StevenBucher98, unfortunately, this is not fixed, which you can verify as follows (after running the code in the initial post): [System.Management.Automation.ProxyCommand]::Create($cmdMetadata, "HelpContent", $true) -match 'dynamicparam' It should return |
Yep you are right @mklement0, not sure what I did back in June but I will reopen 😄 |
This issue has been marked as fixed and has not had any activity for 1 day. It has been closed for housekeeping purposes. |
Glad to hear it, @StevenBucher98, but it looks like you'll have to re-open again and remove the |
Hi, I just hit this issue myself. It looks like the overload for
My ignorance may be showing, but I think I've fixed it in https://github.com/fsackur/PowerShell/tree/Fix_CommandMetadata_ImplementsDynamicParameters Output from the repro snippet[CmdletBinding(DefaultParameterSetName='Name')]
param(
[Parameter(ParameterSetName='Name', Mandatory=$true)]
[ValidateSet('Orange','Apple')]
[string]
${Name},
[Parameter(ParameterSetName='Id', Mandatory=$true)]
[ValidateRange(1, 5)]
[int]
${Id},
[Parameter(ValueFromPipeline=$true)]
[string]
${Message})
dynamicparam
{
try {
$targetCmd = $ExecutionContext.InvokeCommand.GetCommand('ProxyTest', [System.Management.Automation.CommandTypes]::Function, $PSBoundParameters)
$dynamicParams = @($targetCmd.Parameters.GetEnumerator() | Microsoft.PowerShell.Core\Where-Object { $_.Value.IsDynamic })
if ($dynamicParams.Length -gt 0)
{
$paramDictionary = [Management.Automation.RuntimeDefinedParameterDictionary]::new()
foreach ($param in $dynamicParams)
{
$param = $param.Value
if(-not $MyInvocation.MyCommand.Parameters.ContainsKey($param.Name))
{
$dynParam = [Management.Automation.RuntimeDefinedParameter]::new($param.Name, $param.ParameterType, $param.Attributes)
$paramDictionary.Add($param.Name, $dynParam)
}
}
return $paramDictionary
}
} catch {
throw
}
}
begin
{
try {
$outBuffer = $null
if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
{
$PSBoundParameters['OutBuffer'] = 1
}
$wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('ProxyTest', [System.Management.Automation.CommandTypes]::Function)
$scriptCmd = {& $wrappedCmd @PSBoundParameters }
$steppablePipeline = $scriptCmd.GetSteppablePipeline()
$steppablePipeline.Begin($PSCmdlet)
} catch {
throw
}
}
process
{
try {
$steppablePipeline.Process($_)
} catch {
throw
}
}
end
{
try {
$steppablePipeline.End()
} catch {
throw
}
}
clean
{
if ($null -ne $steppablePipeline) {
$steppablePipeline.Clean()
}
}
<#
HelpContent
#> Would a maintainer be willing to look at a PR? |
@mklement0 Whatever broke the build on mac is fixed, and my PR is green. It's only small - any chance of a review? |
@fsackur, others are better qualified to conduct reviews, perhaps @daxian-dbw or @IISResetMe. |
Hi @daxian-dbw or @IISResetMe - this is a small change, but the bug bothered me and cost me a day; would either of you be willing to review it? |
I also would find this incredibly useful for a module I'm working on that I have to work around with a ton more effort. |
Steps to reproduce
Expected behavior
There is dynamic parameters defined in the function
ProxyTest
:And when calling
[ProxyCommand]::Create
, the$true
is the value for parameterbool generateDynamicParameters
, so it should generate the dynamic param block in the proxy script.However, the returned script has
DynamicParam
block in it.Actual behavior
No
DynamicParam
block generated.But if it's a binary cmdlet instead of a function, then the
dynamicparam
block is correctly generated.Environment data
This happens in powershell core and windows powershell.
The cause might be that the constructor
public CommandMetadata(CommandInfo commandInfo)
never check if dynamic parameters are defined forCommandInfo
arguments that are other thanCmdletInfo
. This code ininternal CommandMetadata(ScriptBlock scriptblock ..
probably should be moved toInit(ScriptBlock scriptBlock, string name, bool shouldGenerateCommonParameters)
.The text was updated successfully, but these errors were encountered: