private bool PrepareCommandElements(ExecutionContext context) { int commandIndex = 0; bool dotSource = _commandAst.InvocationOperator == TokenKind.Dot; CommandProcessorBase processor = null; string commandName = null; bool psuedoWorkflowCommand = false; try { processor = PrepareFromAst(context, out commandName) ?? context.CreateCommand(commandName, dotSource); } catch (RuntimeException rte) { // Failed to create the CommandProcessor; CommandProcessorBase.CheckForSevereException(rte); if (_commandAst.IsInWorkflow() && commandName != null && CompletionCompleters.PseudoWorkflowCommands.Contains(commandName, StringComparer.OrdinalIgnoreCase)) { psuedoWorkflowCommand = true; } else { return false; } } var commandProcessor = processor as CommandProcessor; var scriptProcessor = processor as ScriptCommandProcessorBase; bool implementsDynamicParameters = commandProcessor != null && commandProcessor.CommandInfo.ImplementsDynamicParameters; var argumentsToGetDynamicParameters = implementsDynamicParameters ? new List<object>(_commandElements.Count) : null; if (commandProcessor != null || scriptProcessor != null || psuedoWorkflowCommand) { // Pre-processing the arguments -- command arguments for (commandIndex++; commandIndex < _commandElements.Count; commandIndex++) { var parameter = _commandElements[commandIndex] as CommandParameterAst; if (parameter != null) { if (argumentsToGetDynamicParameters != null) { argumentsToGetDynamicParameters.Add(parameter.Extent.Text); } AstPair parameterArg = parameter.Argument != null ? new AstPair(parameter) : new AstPair(parameter, (ExpressionAst)null); _arguments.Add(parameterArg); } else { var dash = _commandElements[commandIndex] as StringConstantExpressionAst; if (dash != null && dash.Value.Trim().Equals("-", StringComparison.OrdinalIgnoreCase)) { // "-" is represented by StringConstantExpressionAst. Most likely the user type a tab here, // and we don't want it be treated as an argument continue; } var expressionArgument = _commandElements[commandIndex] as ExpressionAst; if (expressionArgument != null) { if (argumentsToGetDynamicParameters != null) { argumentsToGetDynamicParameters.Add(expressionArgument.Extent.Text); } _arguments.Add(new AstPair(null, expressionArgument)); } } } } if (commandProcessor != null) { _function = false; if (implementsDynamicParameters) { ParameterBinderController.AddArgumentsToCommandProcessor(commandProcessor, argumentsToGetDynamicParameters.ToArray()); bool retryWithNoArgs = false, alreadyRetried = false; do { CommandProcessorBase oldCurrentCommandProcessor = context.CurrentCommandProcessor; try { context.CurrentCommandProcessor = commandProcessor; commandProcessor.SetCurrentScopeToExecutionScope(); // Run method "BindCommandLineParametersNoValidation" to get all available parameters, including the dynamic // parameters (some of them, not necessarilly all. Since we don't do the actual binding, some dynamic parameters // might not be retrieved). if (!retryWithNoArgs) { // Win8 345299: First try with all unbounded arguments commandProcessor.CmdletParameterBinderController.BindCommandLineParametersNoValidation(commandProcessor.arguments); } else { // Win8 345299: If the first try ended with ParameterBindingException, try again with no arguments alreadyRetried = true; commandProcessor.CmdletParameterBinderController.ClearUnboundArguments(); commandProcessor.CmdletParameterBinderController.BindCommandLineParametersNoValidation(new Collection<CommandParameterInternal>()); } } catch (ParameterBindingException e) { // Catch the parameter binding exception thrown when Reparsing the argument. // "MissingArgument" - a single parameter is matched, but no argument is present // "AmbiguousParameter" - multiple parameters are matched // When such exceptions are caught, retry again without arguments, so as to get dynamic parameters // based on the current provider if (e.ErrorId == "MissingArgument" || e.ErrorId == "AmbiguousParameter") retryWithNoArgs = true; } catch (Exception e) { CommandProcessorBase.CheckForSevereException(e); } finally { context.CurrentCommandProcessor = oldCurrentCommandProcessor; commandProcessor.RestorePreviousScope(); } } while (retryWithNoArgs && !alreadyRetried); } // Get all bindable parameters and initialize the _unboundParameters _commandInfo = commandProcessor.CommandInfo; _commandName = commandProcessor.CommandInfo.Name; _bindableParameters = commandProcessor.CmdletParameterBinderController.BindableParameters; _defaultParameterSetFlag = commandProcessor.CommandInfo.CommandMetadata.DefaultParameterSetFlag; } else if (scriptProcessor != null) { _function = true; _commandInfo = scriptProcessor.CommandInfo; _commandName = scriptProcessor.CommandInfo.Name; _bindableParameters = scriptProcessor.ScriptParameterBinderController.BindableParameters; _defaultParameterSetFlag = 0; } else if (!psuedoWorkflowCommand) { // The command is not a function, cmdlet and script cmdlet return false; } if (_commandAst.IsInWorkflow()) { var converterType = Type.GetType(Utils.WorkflowType); if (converterType != null) { var activityParameters = (Dictionary<string, Type>)converterType.GetMethod("GetActivityParameters").Invoke(null, new object[] { _commandAst }); if (activityParameters != null) { bool needToRemoveReplacedProperty = activityParameters.ContainsKey("PSComputerName") && !activityParameters.ContainsKey("ComputerName"); var parametersToAdd = new List<MergedCompiledCommandParameter>(); var attrCollection = new Collection<Attribute> { new ParameterAttribute() }; foreach (var pair in activityParameters) { if (psuedoWorkflowCommand || !_bindableParameters.BindableParameters.ContainsKey(pair.Key)) { Type parameterType = GetActualActivityParameterType(pair.Value); var runtimeDefinedParameter = new RuntimeDefinedParameter(pair.Key, parameterType, attrCollection); var compiledCommandParameter = new CompiledCommandParameter(runtimeDefinedParameter, false) { IsInAllSets = true }; var mergedCompiledCommandParameter = new MergedCompiledCommandParameter(compiledCommandParameter, ParameterBinderAssociation.DeclaredFormalParameters); parametersToAdd.Add(mergedCompiledCommandParameter); } } if (parametersToAdd.Any()) { var mergedBindableParameters = new MergedCommandParameterMetadata(); if (!psuedoWorkflowCommand) { mergedBindableParameters.ReplaceMetadata(_bindableParameters); } foreach (var p in parametersToAdd) { mergedBindableParameters.BindableParameters.Add(p.Parameter.Name, p); } _bindableParameters = mergedBindableParameters; } // Remove common parameters that are supported by all commands, but not // by workflows bool fixedReadOnly = false; foreach (var ignored in _ignoredWorkflowParameters) { if (_bindableParameters.BindableParameters.ContainsKey(ignored)) { // However, some ignored parameters are explicitly implemented by // activities, so keep them. if (!activityParameters.ContainsKey(ignored)) { if (!fixedReadOnly) { _bindableParameters.ResetReadOnly(); fixedReadOnly = true; } _bindableParameters.BindableParameters.Remove(ignored); } } } if (_bindableParameters.BindableParameters.ContainsKey("ComputerName") && needToRemoveReplacedProperty) { if (!fixedReadOnly) { _bindableParameters.ResetReadOnly(); fixedReadOnly = true; } _bindableParameters.BindableParameters.Remove("ComputerName"); string aliasOfComputerName = (from aliasPair in _bindableParameters.AliasedParameters where String.Equals("ComputerName", aliasPair.Value.Parameter.Name) select aliasPair.Key).FirstOrDefault(); if (aliasOfComputerName != null) { _bindableParameters.AliasedParameters.Remove(aliasOfComputerName); } } } } } _unboundParameters.AddRange(_bindableParameters.BindableParameters.Values); // Pre-processing the arguments -- pipeline input // Check if there is pipeline input CommandBaseAst preCmdBaseAst = null; var pipe = _commandAst.Parent as PipelineAst; Diagnostics.Assert(pipe != null, "CommandAst should has a PipelineAst parent"); if (pipe.PipelineElements.Count > 1) { foreach (CommandBaseAst cmdBase in pipe.PipelineElements) { if (cmdBase.GetHashCode() == _commandAst.GetHashCode()) { _isPipelineInputExpected = preCmdBaseAst != null; if (_isPipelineInputExpected) _pipelineInputType = typeof(object); break; } preCmdBaseAst = cmdBase; } } return true; }
/// <summary> /// Initialize collection/dictionary members when it's necessary /// </summary> private void InitializeMembers() { List<string> supportedCommonParameters = new List<string>() { "Verbose", "Debug", "ErrorAction", "WarningAction", "InformationAction" }; _ignoredWorkflowParameters = new List<string>(Cmdlet.CommonParameters.Concat<string>(Cmdlet.OptionalCommonParameters)); _ignoredWorkflowParameters.RemoveAll(item => supportedCommonParameters.Contains(item, StringComparer.OrdinalIgnoreCase)); // Initializing binding realted members _function = false; _commandName = null; _currentParameterSetFlag = uint.MaxValue; _defaultParameterSetFlag = 0; _bindableParameters = null; // reuse the collections/dictionaries _arguments = _arguments ?? new Collection<AstParameterArgumentPair>(); _boundParameters = _boundParameters ?? new Dictionary<string, MergedCompiledCommandParameter>(StringComparer.OrdinalIgnoreCase); _boundArguments = _boundArguments ?? new Dictionary<string, AstParameterArgumentPair>(StringComparer.OrdinalIgnoreCase); _unboundParameters = _unboundParameters ?? new List<MergedCompiledCommandParameter>(); _boundPositionalParameter = _boundPositionalParameter ?? new Collection<string>(); _bindingExceptions = _bindingExceptions ?? new Dictionary<CommandParameterAst, ParameterBindingException>(); _arguments.Clear(); _boundParameters.Clear(); _unboundParameters.Clear(); _boundArguments.Clear(); _boundPositionalParameter.Clear(); _bindingExceptions.Clear(); // Initializing tab expansion related members _pipelineInputType = null; _bindingEffective = true; _isPipelineInputExpected = false; // reuse the collections _parametersNotFound = _parametersNotFound ?? new Collection<CommandParameterAst>(); _ambiguousParameters = _ambiguousParameters ?? new Collection<CommandParameterAst>(); _duplicateParameters = _duplicateParameters ?? new Collection<AstParameterArgumentPair>(); _parametersNotFound.Clear(); _ambiguousParameters.Clear(); _duplicateParameters.Clear(); }