Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
CmdletParameterBinderController.cs4654 linesDownload Raw Back to engine
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Diagnostics.CodeAnalysis;8using System.Globalization;9using System.Linq;10using System.Management.Automation.Host;11using System.Management.Automation.Internal;12using System.Management.Automation.Language;13using System.Management.Automation.Runspaces;14using System.Text;15 16namespace System.Management.Automation17{18    /// <summary>19    /// This is the interface between the CommandProcessor and the various20    /// parameter binders required to bind parameters to a cmdlet.21    /// </summary>22    internal class CmdletParameterBinderController : ParameterBinderController23    {24        #region tracer25 26        [TraceSource("ParameterBinderController", "Controls the interaction between the command processor and the parameter binder(s).")]27        private static readonly PSTraceSource s_tracer = PSTraceSource.GetTracer("ParameterBinderController", "Controls the interaction between the command processor and the parameter binder(s).");28 29        #endregion tracer30 31        #region ctor32 33        /// <summary>34        /// Initializes the cmdlet parameter binder controller for35        /// the specified cmdlet and engine context.36        /// </summary>37        /// <param name="cmdlet">38        /// The cmdlet that the parameters will be bound to.39        /// </param>40        /// <param name="commandMetadata">41        /// The metadata about the cmdlet.42        /// </param>43        /// <param name="parameterBinder">44        /// The default parameter binder to use.45        /// </param>46        internal CmdletParameterBinderController(47            Cmdlet cmdlet,48            CommandMetadata commandMetadata,49            ParameterBinderBase parameterBinder)50            : base(51                cmdlet.MyInvocation,52                cmdlet.Context,53                parameterBinder)54        {55            if (cmdlet == null)56            {57                throw PSTraceSource.NewArgumentNullException(nameof(cmdlet));58            }59 60            if (commandMetadata == null)61            {62                throw PSTraceSource.NewArgumentNullException(nameof(commandMetadata));63            }64 65            this.Command = cmdlet;66            _commandRuntime = (MshCommandRuntime)cmdlet.CommandRuntime;67            _commandMetadata = commandMetadata;68 69            // Add the static parameter metadata to the bindable parameters70            // And add them to the unbound parameters list71 72            if (commandMetadata.ImplementsDynamicParameters)73            {74                // ReplaceMetadata makes a copy for us, so we can use that collection as is.75                this.UnboundParameters = this.BindableParameters.ReplaceMetadata(commandMetadata.StaticCommandParameterMetadata);76            }77            else78            {79                _bindableParameters = commandMetadata.StaticCommandParameterMetadata;80 81                // Must make a copy of the list because we'll modify it.82                this.UnboundParameters = new List<MergedCompiledCommandParameter>(_bindableParameters.BindableParameters.Values);83            }84        }85 86        #endregion ctor87 88        #region helper_methods89 90        /// <summary>91        /// Binds the specified command-line parameters to the target.92        /// </summary>93        /// <param name="arguments">94        /// Parameters to the command.95        /// </param>96        /// <exception cref="ParameterBindingException">97        /// If any parameters fail to bind,98        /// or99        /// If any mandatory parameters are missing.100        /// </exception>101        /// <exception cref="MetadataException">102        /// If there is an error generating the metadata for dynamic parameters.103        /// </exception>104        internal void BindCommandLineParameters(Collection<CommandParameterInternal> arguments)105        {106            s_tracer.WriteLine("Argument count: {0}", arguments.Count);107 108            BindCommandLineParametersNoValidation(arguments);109 110            // Is pipeline input expected?111            bool isPipelineInputExpected = !(_commandRuntime.IsClosed && _commandRuntime.InputPipe.Empty);112 113            int validParameterSetCount;114 115            if (!isPipelineInputExpected)116            {117                // Since pipeline input is not expected, ensure that we have a single118                // parameter set and that all the mandatory119                // parameters for the working parameter set are specified, or prompt120 121                validParameterSetCount = ValidateParameterSets(false, true);122            }123            else124            {125                // Use ValidateParameterSets to get the number of valid parameter126                // sets.127 128                // NTRAID#Windows Out Of Band Releases-2005/11/07-923917-JonN129                validParameterSetCount = ValidateParameterSets(true, false);130            }131 132            // If the parameter set is determined and the default parameters are not used133            // we try the default parameter binding again because it may contain some mandatory134            // parameters135            if (validParameterSetCount == 1 && !DefaultParameterBindingInUse)136            {137                ApplyDefaultParameterBinding("Mandatory Checking", false);138            }139 140            // If there are multiple valid parameter sets and we are expecting pipeline inputs,141            // we should filter out those parameter sets that cannot take pipeline inputs anymore.142            if (validParameterSetCount > 1 && isPipelineInputExpected)143            {144                uint filteredValidParameterSetFlags = FilterParameterSetsTakingNoPipelineInput();145                if (filteredValidParameterSetFlags != _currentParameterSetFlag)146                {147                    _currentParameterSetFlag = filteredValidParameterSetFlags;148                    // The valid parameter set flag is narrowed down, we get the new validParameterSetCount149                    validParameterSetCount = ValidateParameterSets(true, false);150                }151            }152 153            using (ParameterBinderBase.bindingTracer.TraceScope(154                "MANDATORY PARAMETER CHECK on cmdlet [{0}]",155                _commandMetadata.Name))156            {157                try158                {159                    // The missingMandatoryParameters out parameter is used for error reporting when binding from the pipeline.160                    // We're not binding from the pipeline here, and if a mandatory non-pipeline parameter is missing, it will161                    // be prompted for, or an exception will be raised, so we can ignore the missingMandatoryParameters out parameter.162                    Collection<MergedCompiledCommandParameter> missingMandatoryParameters;163 164                    // We shouldn't prompt for mandatory parameters if this command is private.165                    bool promptForMandatoryParameters = (Command.CommandInfo.Visibility == SessionStateEntryVisibility.Public);166                    HandleUnboundMandatoryParameters(validParameterSetCount, true, promptForMandatoryParameters, isPipelineInputExpected, out missingMandatoryParameters);167 168                    if (DefaultParameterBinder is ScriptParameterBinder)169                    {170                        BindUnboundScriptParameters();171                    }172                }173                catch (ParameterBindingException pbex)174                {175                    if (!DefaultParameterBindingInUse)176                    {177                        throw;178                    }179 180                    ThrowElaboratedBindingException(pbex);181                }182            }183 184            // If there is no more expected input, ensure there is a single185            // parameter set selected186 187            if (!isPipelineInputExpected)188            {189                VerifyParameterSetSelected();190            }191 192            // Set the prepipeline parameter set flags so that they can be restored193            // between each pipeline object.194 195            _prePipelineProcessingParameterSetFlags = _currentParameterSetFlag;196        }197 198        /// <summary>199        /// Binds the unbound arguments to parameters but does not200        /// perform mandatory parameter validation or parameter set validation.201        /// </summary>202        internal void BindCommandLineParametersNoValidation(Collection<CommandParameterInternal> arguments)203        {204            var psCompiledScriptCmdlet = this.Command as PSScriptCmdlet;205            psCompiledScriptCmdlet?.PrepareForBinding(this.CommandLineParameters);206 207            InitUnboundArguments(arguments);208            CommandMetadata cmdletMetadata = _commandMetadata;209            // Clear the warningSet at the beginning.210            _warningSet.Clear();211            // Parse $PSDefaultParameterValues to get all valid <parameter, value> pairs212            _allDefaultParameterValuePairs = this.GetDefaultParameterValuePairs(true);213            // Set to false at the beginning214            DefaultParameterBindingInUse = false;215            // Clear the bound default parameters at the beginning216            BoundDefaultParameters.Clear();217 218            // Reparse the arguments based on the merged metadata219            ReparseUnboundArguments();220 221            using (ParameterBinderBase.bindingTracer.TraceScope(222                "BIND NAMED cmd line args [{0}]",223                _commandMetadata.Name))224            {225                // Bind the actual arguments226                UnboundArguments = BindNamedParameters(_currentParameterSetFlag, this.UnboundArguments);227            }228 229            ParameterBindingException reportedBindingException;230            ParameterBindingException currentBindingException;231 232            using (ParameterBinderBase.bindingTracer.TraceScope(233                "BIND POSITIONAL cmd line args [{0}]",234                _commandMetadata.Name))235            {236                // Now that we know the parameter set, bind the positional parameters237                UnboundArguments =238                    BindPositionalParameters(239                        UnboundArguments,240                        _currentParameterSetFlag,241                        cmdletMetadata.DefaultParameterSetFlag,242                        out currentBindingException);243 244                reportedBindingException = currentBindingException;245            }246 247            // Try applying the default parameter binding after POSITIONAL BIND so that the default parameter248            // values can influence the parameter set selection earlier than the default parameter set.249            ApplyDefaultParameterBinding("POSITIONAL BIND", false);250 251            // We need to make sure there is at least one valid parameter set. Its252            // OK to allow more than one as long as one of them takes pipeline input.253 254            // NTRAID#Windows Out Of Band Releases-2006/02/14-928660-JonN255            // Pipeline input fails to bind to pipeline enabled parameter256            // second parameter changed from true to false257            ValidateParameterSets(true, false);258 259            // Always get the dynamic parameters as there may be mandatory parameters there260 261            // Now try binding the dynamic parameters262            HandleCommandLineDynamicParameters(out currentBindingException);263 264            // Try binding the default parameters again. After dynamic binding, new parameter metadata are265            // included, so it's possible a previously unsuccessful binding will succeed.266            ApplyDefaultParameterBinding("DYNAMIC BIND", true);267 268            // If this generated an exception (but we didn't have one from the non-dynamic269            // parameters, report on this one.270            reportedBindingException ??= currentBindingException;271 272            // If the cmdlet implements a ValueFromRemainingArguments parameter (VarArgs)273            // bind the unbound arguments to that parameter.274            HandleRemainingArguments();275 276            VerifyArgumentsProcessed(reportedBindingException);277        }278 279        /// <summary>280        /// Process all valid parameter sets, and filter out those that don't take any pipeline input.281        /// </summary>282        /// <returns>283        /// The new valid parameter set flags284        /// </returns>285        private uint FilterParameterSetsTakingNoPipelineInput()286        {287            uint parameterSetsTakingPipeInput = 0;288            bool findPipeParameterInAllSets = false;289 290            foreach (KeyValuePair<MergedCompiledCommandParameter, DelayedScriptBlockArgument> entry in _delayBindScriptBlocks)291            {292                parameterSetsTakingPipeInput |= entry.Key.Parameter.ParameterSetFlags;293            }294 295            foreach (MergedCompiledCommandParameter parameter in UnboundParameters)296            {297                // If a parameter doesn't take pipeline input at all, we can skip it298                if (!parameter.Parameter.IsPipelineParameterInSomeParameterSet)299                {300                    continue;301                }302 303                var matchingParameterSetMetadata =304                    parameter.Parameter.GetMatchingParameterSetData(_currentParameterSetFlag);305 306                foreach (ParameterSetSpecificMetadata parameterSetMetadata in matchingParameterSetMetadata)307                {308                    if (parameterSetMetadata.ValueFromPipeline || parameterSetMetadata.ValueFromPipelineByPropertyName)309                    {310                        if (parameterSetMetadata.ParameterSetFlag == 0 && parameterSetMetadata.IsInAllSets)311                        {312                            // The parameter takes pipeline input and is in all sets, we don't change the _currentParameterSetFlag313                            parameterSetsTakingPipeInput = 0;314                            findPipeParameterInAllSets = true;315                            break;316                        }317                        else318                        {319                            parameterSetsTakingPipeInput |= parameterSetMetadata.ParameterSetFlag;320                        }321                    }322                }323 324                if (findPipeParameterInAllSets)325                    break;326            }327 328            // If parameterSetsTakingPipeInput is 0, then no parameter set from the _currentParameterSetFlag can take piped objects.329            // Then we just leave what it was, and the pipeline binding deal with the error later330            if (parameterSetsTakingPipeInput != 0)331                return _currentParameterSetFlag & parameterSetsTakingPipeInput;332            else333                return _currentParameterSetFlag;334        }335 336        /// <summary>337        /// Apply the binding for the default parameter defined by the user.338        /// </summary>339        /// <param name="bindingStage">340        /// Dictate which binding stage this default binding happens341        /// </param>342        /// <param name="isDynamic">343        /// Special operation needed if the default binding happens at the dynamic binding stage344        /// </param>345        /// <returns></returns>346        private void ApplyDefaultParameterBinding(string bindingStage, bool isDynamic)347        {348            if (!_useDefaultParameterBinding)349            {350                return;351            }352 353            if (isDynamic)354            {355                // Get user defined default parameter value pairs again, so that the356                // dynamic parameter value pairs could be involved.357                _allDefaultParameterValuePairs = GetDefaultParameterValuePairs(false);358            }359 360            Dictionary<MergedCompiledCommandParameter, object> qualifiedParameterValuePairs = GetQualifiedParameterValuePairs(_currentParameterSetFlag, _allDefaultParameterValuePairs);361            if (qualifiedParameterValuePairs != null)362            {363                bool isSuccess = false;364                using (ParameterBinderBase.bindingTracer.TraceScope(365                    "BIND DEFAULT <parameter, value> pairs after [{0}] for [{1}]",366                    bindingStage, _commandMetadata.Name))367                {368                    isSuccess = BindDefaultParameters(_currentParameterSetFlag, qualifiedParameterValuePairs);369                    if (isSuccess && !DefaultParameterBindingInUse)370                    {371                        DefaultParameterBindingInUse = true;372                    }373                }374 375                s_tracer.WriteLine("BIND DEFAULT after [{0}] result [{1}]", bindingStage, isSuccess);376            }377 378            return;379        }380 381        /// <summary>382        /// Bind the default parameter value pairs.383        /// </summary>384        /// <param name="validParameterSetFlag">ValidParameterSetFlag.</param>385        /// <param name="defaultParameterValues">Default value pairs.</param>386        /// <returns>387        /// true if there is at least one default parameter bound successfully388        /// false if there is no default parameter bound successfully389        /// </returns>390        private bool BindDefaultParameters(uint validParameterSetFlag, Dictionary<MergedCompiledCommandParameter, object> defaultParameterValues)391        {392            bool ret = false;393            foreach (var pair in defaultParameterValues)394            {395                MergedCompiledCommandParameter parameter = pair.Key;396                object argumentValue = pair.Value;397                string parameterName = parameter.Parameter.Name;398 399                try400                {401                    ScriptBlock scriptBlockArg = argumentValue as ScriptBlock;402                    if (scriptBlockArg != null)403                    {404                        // Get the current binding state, and pass it to the ScriptBlock as the argument405                        // The 'arg' includes HashSet properties 'BoundParameters', 'BoundPositionalParameters',406                        // 'BoundDefaultParameters', and 'LastBindingStage'. So the user can set value407                        // to a parameter depending on the current binding state.408                        PSObject arg = WrapBindingState();409                        Collection<PSObject> results = scriptBlockArg.Invoke(arg);410                        if (results == null || results.Count == 0)411                        {412                            continue;413                        }414                        else if (results.Count == 1)415                        {416                            argumentValue = results[0];417                        }418                        else419                        {420                            argumentValue = results;421                        }422                    }423 424                    CommandParameterInternal bindableArgument =425                        CommandParameterInternal.CreateParameterWithArgument(426                           /*parameterAst*/null, parameterName, "-" + parameterName + ":",427                           /*argumentAst*/null, argumentValue, false);428 429                    bool bindResult =430                            BindParameter(431                                validParameterSetFlag,432                                bindableArgument,433                                parameter,434                                ParameterBindingFlags.ShouldCoerceType | ParameterBindingFlags.DelayBindScriptBlock);435 436                    if (bindResult && !ret)437                    {438                        ret = true;439                    }440 441                    if (bindResult)442                    {443                        BoundDefaultParameters.Add(parameterName);444                    }445                }446                catch (ParameterBindingException ex)447                {448                    // We don't want the failures in default binding affect the command line binding,449                    // so we write out a warning and ignore this binding failure450                    if (!_warningSet.Contains(_commandMetadata.Name + Separator + parameterName))451                    {452                        string message = string.Format(CultureInfo.InvariantCulture,453                            ParameterBinderStrings.FailToBindDefaultParameter,454                            LanguagePrimitives.IsNull(argumentValue) ? "null" : argumentValue.ToString(),455                            parameterName, ex.Message);456                        _commandRuntime.WriteWarning(message);457                        _warningSet.Add(_commandMetadata.Name + Separator + parameterName);458                    }459 460                    continue;461                }462            }463 464            return ret;465        }466 467        /// <summary>468        /// Wrap up current binding state to provide more information to the user.469        /// </summary>470        /// <returns></returns>471        private PSObject WrapBindingState()472        {473            HashSet<string> boundParameterNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);474            HashSet<string> boundPositionalParameterNames =475                this.DefaultParameterBinder.CommandLineParameters.CopyBoundPositionalParameters();476            HashSet<string> boundDefaultParameterNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);477 478            foreach (string paramName in BoundParameters.Keys)479            {480                boundParameterNames.Add(paramName);481            }482 483            foreach (string paramName in BoundDefaultParameters)484            {485                boundDefaultParameterNames.Add(paramName);486            }487 488            PSObject result = new PSObject();489            result.Properties.Add(new PSNoteProperty("BoundParameters", boundParameterNames));490            result.Properties.Add(new PSNoteProperty("BoundPositionalParameters", boundPositionalParameterNames));491            result.Properties.Add(new PSNoteProperty("BoundDefaultParameters", boundDefaultParameterNames));492 493            return result;494        }495 496        /// <summary>497        /// Get all qualified default parameter value pairs based on the498        /// given currentParameterSetFlag.499        /// </summary>500        /// <param name="currentParameterSetFlag"></param>501        /// <param name="availableParameterValuePairs"></param>502        /// <returns>Null if no qualified pair found.</returns>503        private Dictionary<MergedCompiledCommandParameter, object> GetQualifiedParameterValuePairs(504            uint currentParameterSetFlag,505            Dictionary<MergedCompiledCommandParameter, object> availableParameterValuePairs)506        {507            if (availableParameterValuePairs == null)508            {509                return null;510            }511 512            Dictionary<MergedCompiledCommandParameter, object> result = new Dictionary<MergedCompiledCommandParameter, object>();513 514            uint possibleParameterFlag = uint.MaxValue;515            foreach (var pair in availableParameterValuePairs)516            {517                MergedCompiledCommandParameter param = pair.Key;518                if ((param.Parameter.ParameterSetFlags & currentParameterSetFlag) == 0 && !param.Parameter.IsInAllSets)519                {520                    continue;521                }522 523                if (BoundArguments.ContainsKey(param.Parameter.Name))524                {525                    continue;526                }527 528                // check if this param's set conflicts with other possible params.529                if (param.Parameter.ParameterSetFlags != 0)530                {531                    possibleParameterFlag &= param.Parameter.ParameterSetFlags;532                    if (possibleParameterFlag == 0)533                    {534                        return null;535                    }536                }537 538                result.Add(param, pair.Value);539            }540 541            if (result.Count > 0)542            {543                return result;544            }545 546            return null;547        }548 549        /// <summary>550        /// Get the aliases of the current cmdlet.551        /// </summary>552        /// <returns></returns>553        private List<string> GetAliasOfCurrentCmdlet()554        {555            var results = Context.SessionState.Internal.GetAliasesByCommandName(_commandMetadata.Name).ToList();556 557            return results.Count > 0 ? results : null;558        }559 560        /// <summary>561        /// Check if the passed-in aliasName matches an alias name in _aliasList.562        /// </summary>563        /// <param name="aliasName"></param>564        /// <returns></returns>565        private bool MatchAnyAlias(string aliasName)566        {567            if (_aliasList == null)568            {569                return false;570            }571 572            bool result = false;573            WildcardPattern aliasPattern = WildcardPattern.Get(aliasName, WildcardOptions.IgnoreCase);574            foreach (string alias in _aliasList)575            {576                if (aliasPattern.IsMatch(alias))577                {578                    result = true;579                    break;580                }581            }582 583            return result;584        }585 586        internal IDictionary DefaultParameterValues { get; set; }587        /// <summary>588        /// Get all available default parameter value pairs.589        /// </summary>590        /// <returns>Return the available parameter value pairs. Otherwise return null.</returns>591        private Dictionary<MergedCompiledCommandParameter, object> GetDefaultParameterValuePairs(bool needToGetAlias)592        {593            if (DefaultParameterValues == null)594            {595                _useDefaultParameterBinding = false;596                return null;597            }598 599            var availablePairs = new Dictionary<MergedCompiledCommandParameter, object>();600 601            if (needToGetAlias && DefaultParameterValues.Count > 0)602            {603                // Get all aliases of the current cmdlet604                _aliasList = GetAliasOfCurrentCmdlet();605            }606 607            // Set flag to true by default608            _useDefaultParameterBinding = true;609 610            string currentCmdletName = _commandMetadata.Name;611 612            IDictionary<string, MergedCompiledCommandParameter> bindableParameters = BindableParameters.BindableParameters;613            IDictionary<string, MergedCompiledCommandParameter> bindableAlias = BindableParameters.AliasedParameters;614 615            // Contains parameters that are set with different values by settings in $PSDefaultParameterValues.616            // We should ignore those settings and write out a warning617            var parametersToRemove = new HashSet<MergedCompiledCommandParameter>();618            var wildcardDefault = new Dictionary<string, object>();619            // Contains keys that are in bad format. For every bad format key, we should write out a warning message620            // the first time we encounter it, and remove it from the $PSDefaultParameterValues621            var keysToRemove = new List<object>();622 623            foreach (DictionaryEntry entry in DefaultParameterValues)624            {625                if (entry.Key is not string key)626                {627                    continue;628                }629 630                key = key.Trim();631                string cmdletName = null;632                string parameterName = null;633 634                // The key is not in valid format635                if (!DefaultParameterDictionary.CheckKeyIsValid(key, ref cmdletName, ref parameterName))636                {637                    if (key.Equals("Disabled", StringComparison.OrdinalIgnoreCase) &&638                        LanguagePrimitives.IsTrue(entry.Value))639                    {640                        _useDefaultParameterBinding = false;641                        return null;642                    }643                    // Write out a warning message if the key is not 'Disabled'644                    if (!key.Equals("Disabled", StringComparison.OrdinalIgnoreCase))645                    {646                        keysToRemove.Add(entry.Key);647                    }648 649                    continue;650                }651 652                Diagnostics.Assert(cmdletName != null && parameterName != null, "The cmdletName and parameterName should be set in CheckKeyIsValid");653 654                if (WildcardPattern.ContainsWildcardCharacters(key))655                {656                    wildcardDefault.Add(cmdletName + Separator + parameterName, entry.Value);657                    continue;658                }659 660                // Continue to process this entry only if the specified cmdletName is the name661                // of the current cmdlet, or is an alias name of the current cmdlet.662                if (!cmdletName.Equals(currentCmdletName, StringComparison.OrdinalIgnoreCase) && !MatchAnyAlias(cmdletName))663                {664                    continue;665                }666 667                GetDefaultParameterValuePairsHelper(668                    cmdletName, parameterName, entry.Value,669                    bindableParameters, bindableAlias,670                    availablePairs, parametersToRemove);671            }672 673            foreach (KeyValuePair<string, object> wildcard in wildcardDefault)674            {675                string key = wildcard.Key;676 677                string cmdletName = key.Substring(0, key.IndexOf(Separator, StringComparison.OrdinalIgnoreCase));678                string parameterName = key.Substring(key.IndexOf(Separator, StringComparison.OrdinalIgnoreCase) + Separator.Length);679 680                WildcardPattern cmdletPattern = WildcardPattern.Get(cmdletName, WildcardOptions.IgnoreCase);681                // Continue to process this entry only if the cmdletName matches the name of the current682                // cmdlet, or matches an alias name of the current cmdlet683                if (!cmdletPattern.IsMatch(currentCmdletName) && !MatchAnyAlias(cmdletName))684                {685                    continue;686                }687 688                if (!WildcardPattern.ContainsWildcardCharacters(parameterName))689                {690                    GetDefaultParameterValuePairsHelper(691                        cmdletName, parameterName, wildcard.Value,692                        bindableParameters, bindableAlias,693                        availablePairs, parametersToRemove);694 695                    continue;696                }697 698                WildcardPattern parameterPattern = MemberMatch.GetNamePattern(parameterName);699                var matches = new List<MergedCompiledCommandParameter>();700 701                foreach (KeyValuePair<string, MergedCompiledCommandParameter> entry in bindableParameters)702                {703                    if (parameterPattern.IsMatch(entry.Key))704                    {705                        matches.Add(entry.Value);706                    }707                }708 709                foreach (KeyValuePair<string, MergedCompiledCommandParameter> entry in bindableAlias)710                {711                    if (parameterPattern.IsMatch(entry.Key))712                    {713                        matches.Add(entry.Value);714                    }715                }716 717                if (matches.Count > 1)718                {719                    // The parameterPattern matches more than one parameters, so we write out a warning message and ignore this setting720                    if (!_warningSet.Contains(cmdletName + Separator + parameterName))721                    {722                        _commandRuntime.WriteWarning(723                            string.Format(CultureInfo.InvariantCulture, ParameterBinderStrings.MultipleParametersMatched, parameterName));724                        _warningSet.Add(cmdletName + Separator + parameterName);725                    }726 727                    continue;728                }729 730                if (matches.Count == 1)731                {732                    if (!availablePairs.ContainsKey(matches[0]))733                    {734                        availablePairs.Add(matches[0], wildcard.Value);735                        continue;736                    }737 738                    if (!wildcard.Value.Equals(availablePairs[matches[0]]))739                    {740                        if (!_warningSet.Contains(cmdletName + Separator + parameterName))741                        {742                            _commandRuntime.WriteWarning(743                                string.Format(CultureInfo.InvariantCulture, ParameterBinderStrings.DifferentValuesAssignedToSingleParameter, parameterName));744                            _warningSet.Add(cmdletName + Separator + parameterName);745                        }746 747                        parametersToRemove.Add(matches[0]);748                    }749                }750            }751 752            if (keysToRemove.Count > 0)753            {754                var keysInError = new StringBuilder();755                foreach (object badFormatKey in keysToRemove)756                {757                    if (DefaultParameterValues.Contains(badFormatKey))758                        DefaultParameterValues.Remove(badFormatKey);759 760                    keysInError.Append(badFormatKey.ToString() + ", ");761                }762 763                keysInError.Remove(keysInError.Length - 2, 2);764                var multipleKeys = keysToRemove.Count > 1;765                string formatString = multipleKeys766                                            ? ParameterBinderStrings.MultipleKeysInBadFormat767                                            : ParameterBinderStrings.SingleKeyInBadFormat;768                _commandRuntime.WriteWarning(769                    string.Format(CultureInfo.InvariantCulture, formatString, keysInError));770            }771 772            foreach (MergedCompiledCommandParameter param in parametersToRemove)773            {774                availablePairs.Remove(param);775            }776 777            if (availablePairs.Count > 0)778            {779                return availablePairs;780            }781 782            return null;783        }784 785        /// <summary>786        /// A helper method for GetDefaultParameterValuePairs.787        /// </summary>788        /// <param name="cmdletName"></param>789        /// <param name="paramName"></param>790        /// <param name="paramValue"></param>791        /// <param name="bindableParameters"></param>792        /// <param name="bindableAlias"></param>793        /// <param name="result"></param>794        /// <param name="parametersToRemove"></param>795        private void GetDefaultParameterValuePairsHelper(796            string cmdletName, string paramName, object paramValue,797            IDictionary<string, MergedCompiledCommandParameter> bindableParameters,798            IDictionary<string, MergedCompiledCommandParameter> bindableAlias,799            Dictionary<MergedCompiledCommandParameter, object> result,800            HashSet<MergedCompiledCommandParameter> parametersToRemove)801        {802            // No exception should be thrown if we cannot find a match for the 'paramName',803            // because the 'paramName' could be a dynamic parameter name, and this dynamic parameter804            // hasn't been introduced at the current stage.805            bool writeWarning = false;806            MergedCompiledCommandParameter matchParameter;807            object resultObject;808            if (bindableParameters.TryGetValue(paramName, out matchParameter))809            {810                if (!result.TryGetValue(matchParameter, out resultObject))811                {812                    result.Add(matchParameter, paramValue);813                    return;814                }815 816                if (!paramValue.Equals(resultObject))817                {818                    writeWarning = true;819                    parametersToRemove.Add(matchParameter);820                }821            }822            else823            {824                if (bindableAlias.TryGetValue(paramName, out matchParameter))825                {826                    if (!result.TryGetValue(matchParameter, out resultObject))827                    {828                        result.Add(matchParameter, paramValue);829                        return;830                    }831 832                    if (!paramValue.Equals(resultObject))833                    {834                        writeWarning = true;835                        parametersToRemove.Add(matchParameter);836                    }837                }838            }839 840            if (writeWarning && !_warningSet.Contains(cmdletName + Separator + paramName))841            {842                _commandRuntime.WriteWarning(843                    string.Format(CultureInfo.InvariantCulture, ParameterBinderStrings.DifferentValuesAssignedToSingleParameter, paramName));844                _warningSet.Add(cmdletName + Separator + paramName);845            }846        }847 848        /// <summary>849        /// Verify if all arguments from the command line are bound.850        /// </summary>851        /// <param name="originalBindingException">852        /// Previous binding exceptions that possibly causes the failure853        /// </param>854        private void VerifyArgumentsProcessed(ParameterBindingException originalBindingException)855        {856            // Now verify that all the arguments that were passed in were processed.857 858            if (UnboundArguments.Count > 0)859            {860                ParameterBindingException bindingException;861                CommandParameterInternal parameter = UnboundArguments[0];862 863                // Get the argument type that was specified864 865                Type specifiedType = null;866                object argumentValue = parameter.ArgumentValue;867                if (argumentValue != null && argumentValue != UnboundParameter.Value)868                {869                    specifiedType = argumentValue.GetType();870                }871 872                if (parameter.ParameterNameSpecified)873                {874                    bindingException =875                        new ParameterBindingException(876                            ErrorCategory.InvalidArgument,877                            this.Command.MyInvocation,878                            GetParameterErrorExtent(parameter),879                            parameter.ParameterName,880                            null,881                            specifiedType,882                            ParameterBinderStrings.NamedParameterNotFound,883                            "NamedParameterNotFound");884                }885                else886                {887                    // If this was a positional parameter, and we have the original exception,888                    // report on the original error889                    if (originalBindingException != null)890                    {891                        bindingException = originalBindingException;892                    }893                    // Otherwise, give a generic error.894                    else895                    {896                        string argument = StringLiterals.DollarNull;897                        if (parameter.ArgumentValue != null)898                        {899                            try900                            {901                                argument = parameter.ArgumentValue.ToString();902                            }903                            catch (Exception e)904                            {905                                bindingException =906                                    new ParameterBindingArgumentTransformationException(907                                        e,908                                        ErrorCategory.InvalidData,909                                        this.InvocationInfo,910                                        null,911                                        null,912                                        null,913                                        parameter.ArgumentValue.GetType(),914                                        ParameterBinderStrings.ParameterArgumentTransformationErrorMessageOnly,915                                        "ParameterArgumentTransformationErrorMessageOnly",916                                        e.Message);917 918                                if (!DefaultParameterBindingInUse)919                                {920                                    throw bindingException;921                                }922                                else923                                {924                                    ThrowElaboratedBindingException(bindingException);925                                }926                            }927                        }928 929                        bindingException =930                            new ParameterBindingException(931                                ErrorCategory.InvalidArgument,932                                this.Command.MyInvocation,933                                null,934                                argument,935                                null,936                                specifiedType,937                                ParameterBinderStrings.PositionalParameterNotFound,938                                "PositionalParameterNotFound");939                    }940                }941 942                if (!DefaultParameterBindingInUse)943                {944                    throw bindingException;945                }946                else947                {948                    ThrowElaboratedBindingException(bindingException);949                }950            }951        }952 953        /// <summary>954        /// Verifies that a single parameter set is selected and throws an exception if955        /// one of there are multiple and one of them is not the default parameter set.956        /// </summary>957        private void VerifyParameterSetSelected()958        {959            // Now verify that a parameter set has been selected if any parameter sets960            // were defined.961 962            if (this.BindableParameters.ParameterSetCount > 1)963            {964                if (_currentParameterSetFlag == uint.MaxValue)965                {966                    if ((_currentParameterSetFlag &967                         _commandMetadata.DefaultParameterSetFlag) != 0 &&968                         _commandMetadata.DefaultParameterSetFlag != uint.MaxValue)969                    {970                        ParameterBinderBase.bindingTracer.WriteLine(971                            "{0} valid parameter sets, using the DEFAULT PARAMETER SET: [{0}]",972                            this.BindableParameters.ParameterSetCount.ToString(),973                            _commandMetadata.DefaultParameterSetName);974 975                        _currentParameterSetFlag =976                            _commandMetadata.DefaultParameterSetFlag;977                    }978                    else979                    {980                        ParameterBinderBase.bindingTracer.TraceError(981                            "ERROR: {0} valid parameter sets, but NOT DEFAULT PARAMETER SET.",982                            this.BindableParameters.ParameterSetCount);983 984                        // Throw an exception for ambiguous parameter set985                        ThrowAmbiguousParameterSetException(_currentParameterSetFlag, BindableParameters);986                    }987                }988            }989        }990 991        /// <summary>992        /// Restores the specified parameter to the original value.993        /// </summary>994        /// <param name="argumentToBind">995        /// The argument containing the value to restore.996        /// </param>997        /// <param name="parameter">998        /// The metadata for the parameter to restore.999        /// </param>1000        /// <returns>1001        /// True if the parameter was restored correctly, or false otherwise.1002        /// </returns>1003        private bool RestoreParameter(CommandParameterInternal argumentToBind, MergedCompiledCommandParameter parameter)1004        {1005            switch (parameter.BinderAssociation)1006            {1007                case ParameterBinderAssociation.DeclaredFormalParameters:1008                    DefaultParameterBinder.BindParameter(argumentToBind.ParameterName, argumentToBind.ArgumentValue, parameter.Parameter);1009                    break;1010 1011                case ParameterBinderAssociation.CommonParameters:1012                    CommonParametersBinder.BindParameter(argumentToBind.ParameterName, argumentToBind.ArgumentValue, parameter.Parameter);1013                    break;1014 1015                case ParameterBinderAssociation.ShouldProcessParameters:1016                    Diagnostics.Assert(1017                        _commandMetadata.SupportsShouldProcess,1018                        "The metadata for the ShouldProcessParameters should only be available if the command supports ShouldProcess");1019 1020                    ShouldProcessParametersBinder.BindParameter(argumentToBind.ParameterName, argumentToBind.ArgumentValue, parameter.Parameter);1021                    break;1022 1023                case ParameterBinderAssociation.PagingParameters:1024                    Diagnostics.Assert(1025                        _commandMetadata.SupportsPaging,1026                        "The metadata for the PagingParameters should only be available if the command supports paging");1027 1028                    PagingParametersBinder.BindParameter(argumentToBind.ParameterName, argumentToBind.ArgumentValue, parameter.Parameter);1029                    break;1030 1031                case ParameterBinderAssociation.TransactionParameters:1032                    Diagnostics.Assert(1033                        _commandMetadata.SupportsTransactions,1034                        "The metadata for the TransactionParameters should only be available if the command supports Transactions");1035 1036                    TransactionParametersBinder.BindParameter(argumentToBind.ParameterName, argumentToBind.ArgumentValue, parameter.Parameter);1037                    break;1038 1039                case ParameterBinderAssociation.DynamicParameters:1040                    Diagnostics.Assert(1041                        _commandMetadata.ImplementsDynamicParameters,1042                        "The metadata for the dynamic parameters should only be available if the command supports IDynamicParameters");1043 1044                    _dynamicParameterBinder?.BindParameter(argumentToBind.ParameterName, argumentToBind.ArgumentValue, parameter.Parameter);1045 1046                    break;1047            }1048 1049            return true;1050        }1051 1052        /// <summary>1053        /// Validate the given named parameter against the specified parameter set,1054        /// and then bind the argument to the parameter.1055        /// </summary>1056        protected override void BindNamedParameter(1057            uint parameterSets,1058            CommandParameterInternal argument,1059            MergedCompiledCommandParameter parameter)1060        {1061            if ((parameter.Parameter.ParameterSetFlags & parameterSets) == 0 &&1062                !parameter.Parameter.IsInAllSets)1063            {1064                string parameterSetName = BindableParameters.GetParameterSetName(parameterSets);1065 1066                ParameterBindingException bindingException =1067                    new ParameterBindingException(1068                        ErrorCategory.InvalidArgument,1069                        this.Command.MyInvocation,1070                        errorPosition: null,1071                        argument.ParameterName,1072                        parameterType: null,1073                        typeSpecified: null,1074                        ParameterBinderStrings.ParameterNotInParameterSet,1075                        "ParameterNotInParameterSet",1076                        parameterSetName);1077 1078                // Might be caused by default parameter binding1079                if (!DefaultParameterBindingInUse)1080                {1081                    throw bindingException;1082                }1083                else1084                {1085                    ThrowElaboratedBindingException(bindingException);1086                }1087            }1088 1089            try1090            {1091                BindParameter(parameterSets, argument, parameter,1092                    ParameterBindingFlags.ShouldCoerceType | ParameterBindingFlags.DelayBindScriptBlock);1093            }1094            catch (ParameterBindingException pbex)1095            {1096                if (!DefaultParameterBindingInUse)1097                {1098                    throw;1099                }1100 1101                ThrowElaboratedBindingException(pbex);1102            }1103        }1104 1105        /// <summary>1106        /// Determines if a ScriptBlock can be bound directly to the type of the specified parameter.1107        /// </summary>1108        /// <param name="parameter">1109        /// The metadata of the parameter to check the type of.1110        /// </param>1111        /// <returns>1112        /// true if the parameter type is Object, ScriptBlock, derived from ScriptBlock, a1113        /// collection of ScriptBlocks, a collection of Objects, or a collection of types derived from1114        /// ScriptBlock.1115        /// False otherwise.1116        /// </returns>1117        private static bool IsParameterScriptBlockBindable(MergedCompiledCommandParameter parameter)1118        {1119            bool result = false;1120 1121            Type parameterType = parameter.Parameter.Type;1122 1123            do // false loop1124            {1125                if (parameterType == typeof(object))1126                {1127                    result = true;1128                    break;1129                }1130 1131                if (parameterType == typeof(ScriptBlock))1132                {1133                    result = true;1134                    break;1135                }1136 1137                if (parameterType.IsSubclassOf(typeof(ScriptBlock)))1138                {1139                    result = true;1140                    break;1141                }1142 1143                ParameterCollectionTypeInformation parameterCollectionTypeInfo = parameter.Parameter.CollectionTypeInformation;1144                if (parameterCollectionTypeInfo.ParameterCollectionType != ParameterCollectionType.NotCollection)1145                {1146                    if (parameterCollectionTypeInfo.ElementType == typeof(object))1147                    {1148                        result = true;1149                        break;1150                    }1151 1152                    if (parameterCollectionTypeInfo.ElementType == typeof(ScriptBlock))1153                    {1154                        result = true;1155                        break;1156                    }1157 1158                    if (parameterCollectionTypeInfo.ElementType.IsSubclassOf(typeof(ScriptBlock)))1159                    {1160                        result = true;1161                        break;1162                    }1163                }1164            } while (false);1165 1166            s_tracer.WriteLine("IsParameterScriptBlockBindable: result = {0}", result);1167            return result;1168        }1169 1170        /// <summary>1171        /// Binds the specified argument to the specified parameter using the appropriate1172        /// parameter binder. If the argument is of type ScriptBlock and the parameter takes1173        /// pipeline input, then the ScriptBlock is saved off in the delay-bind ScriptBlock1174        /// container for further processing of pipeline input and is not bound as the argument1175        /// to the parameter.1176        /// </summary>1177        /// <param name="parameterSets">1178        /// The parameter set used to bind the arguments.1179        /// </param>1180        /// <param name="argument">1181        /// The argument to be bound.1182        /// </param>1183        /// <param name="parameter">1184        /// The metadata for the parameter to bind the argument to.1185        /// </param>1186        /// <param name="flags">1187        /// Flags for type coercion, validation, and script block binding.1188        ///1189        /// ParameterBindingFlags.DelayBindScriptBlock:1190        /// If set, arguments that are of type ScriptBlock where the parameter is not of type ScriptBlock,1191        /// Object, or PSObject will be stored for execution during pipeline input and not bound as1192        /// an argument to the parameter.1193        /// </param>1194        /// <returns>1195        /// True if the parameter was successfully bound. False if <paramref name="flags"/>1196        /// has the flag <see cref="ParameterBindingFlags.ShouldCoerceType"/> set and the type does not match the parameter type.1197        /// </returns>1198        internal override bool BindParameter(1199            uint parameterSets,1200            CommandParameterInternal argument,

Showing the first 1,200 of 4654 lines. Download the file for the rest.