Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Host;
using System.Management.Automation.Internal;
using System.Management.Automation.Language;
Expand Down Expand Up @@ -202,7 +203,7 @@ internal void BindCommandLineParameters(Collection<CommandParameterInternal> arg
internal void BindCommandLineParametersNoValidation(Collection<CommandParameterInternal> arguments)
{
var psCompiledScriptCmdlet = this.Command as PSScriptCmdlet;
psCompiledScriptCmdlet?.PrepareForBinding(this.CommandLineParameters);
psCompiledScriptCmdlet?.PrepareForBinding(this);

InitUnboundArguments(arguments);
CommandMetadata cmdletMetadata = _commandMetadata;
Expand Down Expand Up @@ -1596,139 +1597,145 @@ private void HandleCommandLineDynamicParameters(out ParameterBindingException ou
{
outgoingBindingException = null;

if (_commandMetadata.ImplementsDynamicParameters)
if (_commandMetadata.ImplementsDynamicParameters && this.Command is IDynamicParameters dynamicParameterCmdlet)
{
using (ParameterBinderBase.bindingTracer.TraceScope(
"BIND cmd line args to DYNAMIC parameters."))
{
s_tracer.WriteLine("The Cmdlet supports the dynamic parameter interface");
if (_dynamicParameterBinder == null)
{
s_tracer.WriteLine("Getting the bindable object from the Cmdlet");

IDynamicParameters dynamicParameterCmdlet = this.Command as IDynamicParameters;
// Now get the dynamic parameter bindable object.
object dynamicParamBindableObject = null;

if (dynamicParameterCmdlet != null)
try
{
if (_dynamicParameterBinder == null)
dynamicParamBindableObject = dynamicParameterCmdlet.GetDynamicParameters();
}
catch (ParameterBindingException e)
{
outgoingBindingException = e;
}
catch (Exception e) // Catch-all OK, this is a third-party callout
{
if (e is ProviderInvocationException)
{
s_tracer.WriteLine("Getting the bindable object from the Cmdlet");

// Now get the dynamic parameter bindable object.
object dynamicParamBindableObject;

try
{
dynamicParamBindableObject = dynamicParameterCmdlet.GetDynamicParameters();
}
catch (Exception e) // Catch-all OK, this is a third-party callout
{
if (e is ProviderInvocationException)
{
throw;
}

ParameterBindingException bindingException =
new ParameterBindingException(
e,
ErrorCategory.InvalidArgument,
this.Command.MyInvocation,
null,
null,
null,
null,
ParameterBinderStrings.GetDynamicParametersException,
"GetDynamicParametersException",
e.Message);

// This exception is caused because failure happens when retrieving the dynamic parameters,
// this is not caused by introducing the default parameter binding.
throw bindingException;
}

if (dynamicParamBindableObject != null)
{
ParameterBinderBase.bindingTracer.WriteLine(
"DYNAMIC parameter object: [{0}]",
dynamicParamBindableObject.GetType());

s_tracer.WriteLine("Creating a new parameter binder for the dynamic parameter object");
throw;
}

InternalParameterMetadata dynamicParameterMetadata;
ParameterBindingException bindingException =
new ParameterBindingException(
e,
ErrorCategory.InvalidArgument,
this.Command.MyInvocation,
null,
null,
null,
null,
ParameterBinderStrings.GetDynamicParametersException,
"GetDynamicParametersException",
e.Message);

RuntimeDefinedParameterDictionary runtimeParamDictionary = dynamicParamBindableObject as RuntimeDefinedParameterDictionary;
if (runtimeParamDictionary != null)
{
// Generate the type metadata for the runtime-defined parameters
dynamicParameterMetadata =
InternalParameterMetadata.Get(runtimeParamDictionary, true, true);

_dynamicParameterBinder =
new RuntimeDefinedParameterBinder(
runtimeParamDictionary,
this.Command,
this.CommandLineParameters);
}
else
{
// Generate the type metadata or retrieve it from the cache
dynamicParameterMetadata =
InternalParameterMetadata.Get(dynamicParamBindableObject.GetType(), Context, true);
// This exception is caused because failure happens when retrieving the dynamic parameters,
// this is not caused by introducing the default parameter binding.
throw bindingException;
}

// Create the parameter binder for the dynamic parameter object
if (dynamicParamBindableObject == null)
{
if (_dynamicParameterBinder == null)
{
s_tracer.WriteLine("No dynamic parameter object or RuntimeDefinedParameters were returned from the Cmdlet");
return;
}else
{
s_tracer.WriteLine("RuntimeDefinedParameters were just-in-time bound from the output pipeline of the dynamicparam block");
}
}
else
{
ParameterBinderBase.bindingTracer.WriteLine(
"DYNAMIC parameter object: [{0}]",
dynamicParamBindableObject.GetType());

_dynamicParameterBinder =
new ReflectionParameterBinder(
dynamicParamBindableObject,
this.Command,
this.CommandLineParameters);
}
// Now merge the metadata with other metadata for the command

// Now merge the metadata with other metadata for the command
MergeStaticAndDynamicParameterMetadata(dynamicParamBindableObject);
}
}
BindDynamicParameters(out outgoingBindingException);
}
}

var dynamicParams =
BindableParameters.AddMetadataForBinder(
dynamicParameterMetadata,
ParameterBinderAssociation.DynamicParameters);
foreach (var param in dynamicParams)
{
UnboundParameters.Add(param);
}
internal void MergeStaticAndDynamicParameterMetadata(object dynamicParamBindableObject)
{
InternalParameterMetadata dynamicParameterMetadata;
if (dynamicParamBindableObject is RuntimeDefinedParameterDictionary runtimeParamDictionary)
{
// Generate the type metadata for the runtime-defined parameters
dynamicParameterMetadata =
InternalParameterMetadata.Get(runtimeParamDictionary, true, true);
s_tracer.WriteLine("Creating a new {0} for the returned RuntimeDefinedParameterDictionary", nameof(RuntimeDefinedParameterBinder));
_dynamicParameterBinder =
new RuntimeDefinedParameterBinder(
runtimeParamDictionary,
this.Command,
this.CommandLineParameters);
}
else
{
// Generate the type metadata or retrieve it from the cache
Type objectType = dynamicParamBindableObject.GetType();
dynamicParameterMetadata =
InternalParameterMetadata.Get(objectType, Context, true);

// Now set the parameter set flags for the new type metadata.
_commandMetadata.DefaultParameterSetFlag =
this.BindableParameters.GenerateParameterSetMappingFromMetadata(_commandMetadata.DefaultParameterSetName);
}
}
// Create the parameter binder for the dynamic parameter object
s_tracer.WriteLine("Creating a new {0} for the returned object type [{1}]", nameof(ReflectionParameterBinder), objectType.FullName);

if (_dynamicParameterBinder == null)
{
s_tracer.WriteLine("No dynamic parameter object was returned from the Cmdlet");
return;
}
_dynamicParameterBinder =
new ReflectionParameterBinder(
dynamicParamBindableObject,
this.Command,
this.CommandLineParameters);
}
var dynamicParams = BindableParameters.AddMetadataForBinder(
dynamicParameterMetadata,
ParameterBinderAssociation.DynamicParameters);
foreach (var param in dynamicParams)
{
UnboundParameters.Add(param);
}
// Now set the parameter set flags for the new type metadata.
_commandMetadata.DefaultParameterSetFlag =
this.BindableParameters.GenerateParameterSetMappingFromMetadata(_commandMetadata.DefaultParameterSetName);
}

if (UnboundArguments.Count > 0)
{
using (ParameterBinderBase.bindingTracer.TraceScope(
"BIND NAMED args to DYNAMIC parameters"))
{
// Try to bind the unbound arguments as static parameters to the
// dynamic parameter object.
internal void BindDynamicParameters(out ParameterBindingException outgoingBindingException)
{
outgoingBindingException = null;
if (UnboundArguments.Count > 0)
{
using (ParameterBinderBase.bindingTracer.TraceScope(
"BIND NAMED args to DYNAMIC parameters"))
{
// Try to bind the unbound arguments as static parameters to the
// dynamic parameter object.

ReparseUnboundArguments();
ReparseUnboundArguments();

UnboundArguments = BindNamedParameters(_currentParameterSetFlag, UnboundArguments);
}
UnboundArguments = BindNamedParameters(_currentParameterSetFlag, UnboundArguments);
}

using (ParameterBinderBase.bindingTracer.TraceScope(
"BIND POSITIONAL args to DYNAMIC parameters"))
{
UnboundArguments =
BindPositionalParameters(
UnboundArguments,
_currentParameterSetFlag,
_commandMetadata.DefaultParameterSetFlag,
out outgoingBindingException);
}
}
}
using (ParameterBinderBase.bindingTracer.TraceScope(
"BIND POSITIONAL args to DYNAMIC parameters"))
{
UnboundArguments =
BindPositionalParameters(
UnboundArguments,
_currentParameterSetFlag,
_commandMetadata.DefaultParameterSetFlag,
out outgoingBindingException);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2412,7 +2412,37 @@ public object GetDynamicParameters()
{
var resultList = new List<object>();
Diagnostics.Assert(_functionContext._outputPipe == null, "Output pipe should not be set yet.");
_functionContext._outputPipe = new Pipe(resultList);
_functionContext._outputPipe = new Pipe();
var objectStream = new ObjectStream();
var objectWriter = new ObjectWriter(objectStream);
objectStream.DataReady += (sender, args) =>
{
var objectStream = sender as ObjectStream;
while (objectStream.Count > 0)
{
var obj = objectStream.Read();
RuntimeDefinedParameter runtimeDefinedParameter = obj as RuntimeDefinedParameter;
runtimeDefinedParameter ??= (obj as PSObject)?.BaseObject as RuntimeDefinedParameter;
if (runtimeDefinedParameter is RuntimeDefinedParameter)
{
RuntimeDefinedParameterDictionary runtimeParamDictionary = new() { { runtimeDefinedParameter.Name, runtimeDefinedParameter } };
_parameterBinderController.MergeStaticAndDynamicParameterMetadata(runtimeParamDictionary);
ParameterBindingException outgoingBindingException = null;
_parameterBinderController.BindDynamicParameters(out outgoingBindingException);
if (outgoingBindingException != null)
{
throw outgoingBindingException;
}
if (this.MyInvocation.BoundParameters.TryGetValue(runtimeDefinedParameter.Name, out var boundValue))
this.SessionState.PSVariable.Set(runtimeDefinedParameter.Name, boundValue);
}
else
{
resultList.Add(obj);
}
}
};
_functionContext._outputPipe.ExternalWriter = objectWriter;
RunClause(
clause: _runOptimized ? _scriptBlock.DynamicParamBlock : _scriptBlock.UnoptimizedDynamicParamBlock,
dollarUnderbar: AutomationNull.Value,
Expand Down Expand Up @@ -2449,11 +2479,12 @@ internal void SetLocalsTupleForNewScope(SessionStateScope scope)
/// </summary>
internal void PopDottedScope(SessionStateScope scope) => scope.DottedScopes.Pop();

internal void PrepareForBinding(CommandLineParameters commandLineParameters)
internal void PrepareForBinding(CmdletParameterBinderController parameterBinderController)
{
_parameterBinderController = parameterBinderController;
_localsTuple.SetAutomaticVariable(
AutomaticVariable.PSBoundParameters,
value: commandLineParameters.GetValueToBindToPSBoundParameters(),
value: _parameterBinderController.CommandLineParameters.GetValueToBindToPSBoundParameters(),
this.Context);
_localsTuple.SetAutomaticVariable(AutomaticVariable.MyInvocation, value: MyInvocation, this.Context);
}
Expand Down Expand Up @@ -2522,6 +2553,7 @@ protected override void StopProcessing()
#region IDispose

private bool _disposed;
private CmdletParameterBinderController _parameterBinderController;

internal event EventHandler DisposingEvent;

Expand Down
Loading