Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
CommandMetadata.cs1552 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;8using System.Globalization;9using System.Management.Automation.Internal;10using System.Management.Automation.Language;11using System.Reflection;12using System.Text;13 14using Microsoft.PowerShell.Commands;15 16using Dbg = System.Diagnostics.Debug;17using System.Diagnostics.CodeAnalysis;18 19namespace System.Management.Automation20{21    /// <summary>22    /// Defines session capabilities provided by a PowerShell session.23    /// </summary>24    /// <seealso cref="System.Management.Automation.Runspaces.InitialSessionState.CreateRestricted"/>25    /// <seealso cref="System.Management.Automation.CommandMetadata.GetRestrictedCommands"/>26    [Flags]27    public enum SessionCapabilities28    {29        /// <summary>30        /// Session with <see cref="RemoteServer"/> capabilities can be made available on a server31        /// that wants to provide a full user experience to PowerShell clients.32        /// Clients connecting to the server will be able to use implicit remoting33        /// (Import-PSSession, Export-PSSession) as well as interactive remoting (Enter-PSSession, Exit-PSSession).34        /// </summary>35        RemoteServer = 0x1,36 37        /// <summary>38        /// Include language capabilities.39        /// </summary>40        Language = 0x441    }42 43    /// <summary>44    /// This class represents the compiled metadata for a command type.45    /// </summary>46    [DebuggerDisplay("CommandName = {Name}; Type = {CommandType}")]47    public sealed class CommandMetadata48    {49        #region Public Constructor50 51        /// <summary>52        /// Constructs a CommandMetadata object for the given CLS complaint type53        /// <paramref name="commandType"/>.54        /// </summary>55        /// <param name="commandType">56        /// CLS complaint type to inspect for Cmdlet metadata.57        /// </param>58        /// <exception cref="ArgumentNullException">59        /// commandType is null.60        /// </exception>61        /// <exception cref="MetadataException">62        /// If a parameter defines the same parameter-set name multiple times.63        /// If the attributes could not be read from a property or field.64        /// </exception>65        public CommandMetadata(Type commandType)66        {67            Init(null, null, commandType, false);68        }69 70        /// <summary>71        /// Construct a CommandMetadata object for the given commandInfo.72        /// </summary>73        /// <param name="commandInfo">74        /// The commandInfo object to construct CommandMetadata for75        /// </param>76        /// <exception cref="ArgumentNullException">77        /// commandInfo is null.78        /// </exception>79        /// <exception cref="PSNotSupportedException">80        /// If the commandInfo is an alias to an unknown command, or if the commandInfo81        /// is an unsupported command type.82        /// </exception>83        public CommandMetadata(CommandInfo commandInfo)84            : this(commandInfo, false)85        {86        }87 88        /// <summary>89        /// Construct a CommandMetadata object for the given commandInfo.90        /// </summary>91        /// <param name="commandInfo">92        /// The commandInfo object to construct CommandMetadata for93        /// </param>94        /// <param name="shouldGenerateCommonParameters">95        /// Should common parameters be included in the metadata?96        /// </param>97        /// <exception cref="ArgumentNullException">98        /// commandInfo is null.99        /// </exception>100        /// <exception cref="PSNotSupportedException">101        /// If the commandInfo is an alias to an unknown command, or if the commandInfo102        /// is an unsupported command type.103        /// </exception>104        public CommandMetadata(CommandInfo commandInfo, bool shouldGenerateCommonParameters)105        {106            if (commandInfo == null)107            {108                throw PSTraceSource.NewArgumentNullException(nameof(commandInfo));109            }110            while (commandInfo is AliasInfo)111            {112                commandInfo = ((AliasInfo)commandInfo).ResolvedCommand;113                if (commandInfo == null)114                {115                    throw PSTraceSource.NewNotSupportedException();116                }117            }118 119            CmdletInfo cmdletInfo;120            ExternalScriptInfo scriptInfo;121            FunctionInfo funcInfo;122            if ((cmdletInfo = commandInfo as CmdletInfo) != null)123            {124                Init(commandInfo.Name, cmdletInfo.FullName, cmdletInfo.ImplementingType, shouldGenerateCommonParameters);125            }126            else if ((scriptInfo = commandInfo as ExternalScriptInfo) != null)127            {128                // Accessing the script block property here reads and parses the script129                Init(scriptInfo.ScriptBlock, scriptInfo.Path, shouldGenerateCommonParameters);130                _wrappedCommandType = CommandTypes.ExternalScript;131            }132            else if ((funcInfo = commandInfo as FunctionInfo) != null)133            {134                Init(funcInfo.ScriptBlock, funcInfo.Name, shouldGenerateCommonParameters);135                _wrappedCommandType = commandInfo.CommandType;136            }137            else138            {139                throw PSTraceSource.NewNotSupportedException();140            }141        }142 143        /// <summary>144        /// Construct a CommandMetadata object for a script file.145        /// </summary>146        /// <param name="path">The path to the script file.</param>147        public CommandMetadata(string path)148        {149            string scriptName = IO.Path.GetFileName(path);150            ExternalScriptInfo scriptInfo = new ExternalScriptInfo(scriptName, path);151 152            Init(scriptInfo.ScriptBlock, path, false);153            _wrappedCommandType = CommandTypes.ExternalScript;154        }155 156        /// <summary>157        /// A copy constructor that creates a deep copy of the <paramref name="other"/> CommandMetadata object.158        /// Instances of Attribute and Type classes are copied by reference.159        /// </summary>160        /// <param name="other">Object to copy.</param>161        public CommandMetadata(CommandMetadata other)162        {163            if (other == null)164            {165                throw PSTraceSource.NewArgumentNullException(nameof(other));166            }167 168            Name = other.Name;169            ConfirmImpact = other.ConfirmImpact;170            _defaultParameterSetFlag = other._defaultParameterSetFlag;171            _defaultParameterSetName = other._defaultParameterSetName;172            _implementsDynamicParameters = other._implementsDynamicParameters;173            SupportsShouldProcess = other.SupportsShouldProcess;174            SupportsPaging = other.SupportsPaging;175            SupportsTransactions = other.SupportsTransactions;176            this.CommandType = other.CommandType;177            _wrappedAnyCmdlet = other._wrappedAnyCmdlet;178            _wrappedCommand = other._wrappedCommand;179            _wrappedCommandType = other._wrappedCommandType;180 181            _parameters = new Dictionary<string, ParameterMetadata>(other.Parameters.Count, StringComparer.OrdinalIgnoreCase);182 183            // deep copy184            foreach (KeyValuePair<string, ParameterMetadata> entry in other.Parameters)185            {186                _parameters.Add(entry.Key, new ParameterMetadata(entry.Value));187            }188 189            // deep copy of the collection, collection items (Attributes) copied by reference190            if (other._otherAttributes == null)191            {192                _otherAttributes = null;193            }194            else195            {196                _otherAttributes = new Collection<Attribute>(new List<Attribute>(other._otherAttributes.Count));197                foreach (Attribute attribute in other._otherAttributes)198                {199                    _otherAttributes.Add(attribute);200                }201            }202 203            // not copying those fields/members as they are untouched (and left set to null)204            // by public constructors, so we can't rely on those fields/members to be set205            // when CommandMetadata comes from a user206            _staticCommandParameterMetadata = null;207        }208 209        /// <summary>210        /// Constructor used by implicit remoting.211        /// </summary>212        internal CommandMetadata(213            string name,214            CommandTypes commandType,215            bool isProxyForCmdlet,216            string defaultParameterSetName,217            bool supportsShouldProcess,218            ConfirmImpact confirmImpact,219            bool supportsPaging,220            bool supportsTransactions,221            bool positionalBinding,222            Dictionary<string, ParameterMetadata> parameters)223        {224            Name = _wrappedCommand = name;225            _wrappedCommandType = commandType;226            _wrappedAnyCmdlet = isProxyForCmdlet;227            _defaultParameterSetName = defaultParameterSetName;228            SupportsShouldProcess = supportsShouldProcess;229            SupportsPaging = supportsPaging;230            ConfirmImpact = confirmImpact;231            SupportsTransactions = supportsTransactions;232            PositionalBinding = positionalBinding;233            this.Parameters = parameters;234        }235 236        private void Init(string name, string fullyQualifiedName, Type commandType, bool shouldGenerateCommonParameters)237        {238            Name = name;239            this.CommandType = commandType;240 241            if (commandType != null)242            {243                ConstructCmdletMetadataUsingReflection();244                _shouldGenerateCommonParameters = shouldGenerateCommonParameters;245            }246 247            // Use fully qualified name if available.248            _wrappedCommand = !string.IsNullOrEmpty(fullyQualifiedName) ? fullyQualifiedName : Name;249            _wrappedCommandType = CommandTypes.Cmdlet;250            _wrappedAnyCmdlet = true;251        }252 253        private void Init(ScriptBlock scriptBlock, string name, bool shouldGenerateCommonParameters)254        {255            if (scriptBlock.UsesCmdletBinding)256            {257                _wrappedAnyCmdlet = true;258            }259            else260            {261                // Ignore what was passed in, there are no common parameters if cmdlet binding is not used.262                shouldGenerateCommonParameters = false;263            }264 265            CmdletBindingAttribute cmdletBindingAttribute = scriptBlock.CmdletBindingAttribute;266            if (cmdletBindingAttribute != null)267            {268                ProcessCmdletAttribute(cmdletBindingAttribute);269            }270            else if (scriptBlock.UsesCmdletBinding)271            {272                _defaultParameterSetName = null;273            }274 275            Obsolete = scriptBlock.ObsoleteAttribute;276            _scriptBlock = scriptBlock;277            _wrappedCommand = Name = name;278            _shouldGenerateCommonParameters = shouldGenerateCommonParameters;279        }280 281        #endregion282 283        #region ctor284 285        /// <summary>286        /// Gets the metadata for the specified cmdlet from the cache or creates287        /// a new instance if its not in the cache.288        /// </summary>289        /// <param name="commandName">290        /// The name of the command that this metadata represents.291        /// </param>292        /// <param name="cmdletType">293        /// The cmdlet to get the metadata for.294        /// </param>295        /// <param name="context">296        /// The current engine context.297        /// </param>298        /// <returns>299        /// The CommandMetadata for the specified cmdlet.300        /// </returns>301        /// <exception cref="ArgumentException">302        /// If <paramref name="commandName"/> is null or empty.303        /// </exception>304        /// <exception cref="ArgumentNullException">305        /// If <paramref name="cmdletType"/> is null.306        /// </exception>307        /// <exception cref="ParsingMetadataException">308        /// If more than int.MaxValue parameter-sets are defined for the command.309        /// </exception>310        /// <exception cref="MetadataException">311        /// If a parameter defines the same parameter-set name multiple times.312        /// If the attributes could not be read from a property or field.313        /// </exception>314        internal static CommandMetadata Get(string commandName, Type cmdletType, ExecutionContext context)315        {316            if (string.IsNullOrEmpty(commandName))317            {318                throw PSTraceSource.NewArgumentException(nameof(commandName));319            }320 321            CommandMetadata result = null;322 323            if ((context != null) && (cmdletType != null))324            {325                string cmdletTypeName = cmdletType.AssemblyQualifiedName;326                s_commandMetadataCache.TryGetValue(cmdletTypeName, out result);327            }328 329            if (result == null)330            {331                result = new CommandMetadata(commandName, cmdletType, context);332 333                if ((context != null) && (cmdletType != null))334                {335                    string cmdletTypeName = cmdletType.AssemblyQualifiedName;336                    s_commandMetadataCache.TryAdd(cmdletTypeName, result);337                }338            }339 340            return result;341        }342 343        /// <summary>344        /// Constructs an instance of CommandMetadata using reflection against a bindable object.345        /// </summary>346        /// <param name="commandName">347        /// The name of the command that this metadata represents.348        /// </param>349        /// <param name="cmdletType">350        /// An instance of an object type that can be used to bind MSH parameters. A type is351        /// considered bindable if it has at least one field and/or property that is decorated352        /// with the ParameterAttribute.353        /// </param>354        /// <param name="context">355        /// The current engine context. If null, the command and type metadata will be generated356        /// and will not be cached.357        /// </param>358        /// <exception cref="ArgumentNullException">359        /// If <paramref name="cmdletType"/> is null.360        /// </exception>361        /// <exception cref="ParsingMetadataException">362        /// If more than int.MaxValue parameter-sets are defined for the command.363        /// </exception>364        /// <exception cref="MetadataException">365        /// If a parameter defines the same parameter-set name multiple times.366        /// If the attributes could not be read from a property or field.367        /// </exception>368        internal CommandMetadata(string commandName, Type cmdletType, ExecutionContext context)369        {370            if (string.IsNullOrEmpty(commandName))371            {372                throw PSTraceSource.NewArgumentException(nameof(commandName));373            }374 375            Name = commandName;376            this.CommandType = cmdletType;377 378            if (cmdletType != null)379            {380                InternalParameterMetadata parameterMetadata = InternalParameterMetadata.Get(cmdletType, context, false);381                ConstructCmdletMetadataUsingReflection();382                _staticCommandParameterMetadata = MergeParameterMetadata(context, parameterMetadata, true);383                _defaultParameterSetFlag = _staticCommandParameterMetadata.GenerateParameterSetMappingFromMetadata(_defaultParameterSetName);384                _staticCommandParameterMetadata.MakeReadOnly();385            }386        }387 388        /// <summary>389        /// Constructor for creating command metadata from a script block.390        /// </summary>391        /// <param name="scriptblock"></param>392        /// <param name="context"></param>393        /// <param name="commandName"></param>394        /// <remarks>395        /// Unlike cmdlet based on a C# type where cmdlet metadata and parameter396        /// metadata is created through reflecting the implementation type, script397        /// cmdlet has different way for constructing metadata.398        ///399        ///     1. Metadata for cmdlet itself comes from cmdlet statement, which400        ///        is parsed into CmdletDeclarationNode and then converted into401        ///        a CmdletAttribute object.402        ///     2. Metadata for parameter comes from parameter declaration statement,403        ///        which is parsed into parameter nodes with parameter annotations.404        ///        Information in ParameterNodes is eventually transformed into a405        ///        dictionary of RuntimeDefinedParameters.406        ///407        /// By the time this constructor is called, information about CmdletAttribute408        /// and RuntimeDefinedParameters for the script block has been setup with409        /// the scriptblock object.410        /// </remarks>411        internal CommandMetadata(ScriptBlock scriptblock, string commandName, ExecutionContext context)412        {413            if (scriptblock == null)414            {415                throw PSTraceSource.NewArgumentException(nameof(scriptblock));416            }417 418            CmdletBindingAttribute cmdletBindingAttribute = scriptblock.CmdletBindingAttribute;419 420            if (cmdletBindingAttribute != null)421            {422                ProcessCmdletAttribute(cmdletBindingAttribute);423            }424            else425            {426                _defaultParameterSetName = null;427            }428 429            Obsolete = scriptblock.ObsoleteAttribute;430            Name = commandName;431            this.CommandType = typeof(PSScriptCmdlet);432 433            if (scriptblock.HasDynamicParameters)434            {435                _implementsDynamicParameters = true;436            }437 438            InternalParameterMetadata parameterMetadata = InternalParameterMetadata.Get(scriptblock.RuntimeDefinedParameters, false,439                                                                                        scriptblock.UsesCmdletBinding);440            _staticCommandParameterMetadata = MergeParameterMetadata(context, parameterMetadata, scriptblock.UsesCmdletBinding);441            _defaultParameterSetFlag = _staticCommandParameterMetadata.GenerateParameterSetMappingFromMetadata(_defaultParameterSetName);442            _staticCommandParameterMetadata.MakeReadOnly();443        }444 445        #endregion ctor446 447        #region Public Properties448 449        /// <summary>450        /// Gets the name of the command this metadata represents.451        /// </summary>452        public string Name { get; set; } = string.Empty;453 454        /// <summary>455        /// The Type which this CommandMetadata represents.456        /// </summary>457        public Type CommandType { get; private set; }458 459        // The ScriptBlock which this CommandMetadata represents.460        private ScriptBlock _scriptBlock;461 462        /// <summary>463        /// Gets/Sets the default parameter set name.464        /// </summary>465        public string DefaultParameterSetName466        {467            get468            {469                return _defaultParameterSetName;470            }471 472            set473            {474                if (string.IsNullOrEmpty(value))475                {476                    value = ParameterAttribute.AllParameterSets;477                }478 479                _defaultParameterSetName = value;480            }481        }482 483        private string _defaultParameterSetName = ParameterAttribute.AllParameterSets;484 485        /// <summary>486        /// True if the cmdlet declared that it supports ShouldProcess, false otherwise.487        /// </summary>488        /// <value></value>489        public bool SupportsShouldProcess { get; set; }490 491        /// <summary>492        /// True if the cmdlet declared that it supports Paging, false otherwise.493        /// </summary>494        /// <value></value>495        public bool SupportsPaging { get; set; }496 497        /// <summary>498        /// When true, the command will auto-generate appropriate parameter metadata to support positional499        /// parameters if the script hasn't already specified multiple parameter sets or specified positions500        /// explicitly via the <see cref="ParameterAttribute"/>.501        /// </summary>502        public bool PositionalBinding { get; set; } = true;503 504        /// <summary>505        /// True if the cmdlet declared that it supports transactions, false otherwise.506        /// </summary>507        /// <value></value>508        public bool SupportsTransactions { get; set; }509 510        /// <summary>511        /// Related link URI for Get-Help -Online.512        /// </summary>513        [SuppressMessage("Microsoft.Design", "CA1056:UriPropertiesShouldNotBeStrings")]514        public string HelpUri { get; set; } = string.Empty;515 516        /// <summary>517        /// The remoting capabilities of this cmdlet, when exposed in a context518        /// with ambient remoting.519        /// </summary>520        public RemotingCapability RemotingCapability521        {522            get523            {524                RemotingCapability currentRemotingCapability = _remotingCapability;525                if ((currentRemotingCapability == Automation.RemotingCapability.PowerShell) &&526                    ((this.Parameters != null) && this.Parameters.ContainsKey("ComputerName")))527                {528                    _remotingCapability = Automation.RemotingCapability.SupportedByCommand;529                }530 531                return _remotingCapability;532            }533 534            set535            {536                _remotingCapability = value;537            }538        }539 540        private RemotingCapability _remotingCapability = RemotingCapability.PowerShell;541 542        /// <summary>543        /// Indicates the "destructiveness" of the command operation and544        /// when it should be confirmed.  This is only effective when545        /// the command calls ShouldProcess, which should only occur when546        /// SupportsShouldProcess is specified.547        /// </summary>548        /// <value></value>549        public ConfirmImpact ConfirmImpact { get; set; } = ConfirmImpact.Medium;550 551        /// <summary>552        /// Gets the parameter data for this command.553        /// </summary>554        public Dictionary<string, ParameterMetadata> Parameters555        {556            get557            {558                if (_parameters == null)559                {560                    // Return parameters for a script block561                    if (_scriptBlock != null)562                    {563                        InternalParameterMetadata parameterMetadata = InternalParameterMetadata.Get(_scriptBlock.RuntimeDefinedParameters, false,564                                                                            _scriptBlock.UsesCmdletBinding);565                        MergedCommandParameterMetadata mergedCommandParameterMetadata =566                            MergeParameterMetadata(null, parameterMetadata, _shouldGenerateCommonParameters);567                        _parameters = ParameterMetadata.GetParameterMetadata(mergedCommandParameterMetadata);568                    }569                    else if (this.CommandType != null)570                    {571                        // Construct compiled parameter metadata from this572                        InternalParameterMetadata parameterMetadata = InternalParameterMetadata.Get(this.CommandType, null, false);573                        MergedCommandParameterMetadata mergedCommandParameterMetadata =574                            MergeParameterMetadata(null, parameterMetadata, _shouldGenerateCommonParameters);575 576                        // Construct parameter metadata from compiled parameter metadata577                        // compiled parameter metadata is used for internal purposes. It has lots of information578                        // which is used by ParameterBinder.579                        _parameters = ParameterMetadata.GetParameterMetadata(mergedCommandParameterMetadata);580                    }581                }582 583                return _parameters;584            }585 586            private set587            {588                _parameters = value;589            }590        }591 592        private Dictionary<string, ParameterMetadata> _parameters;593        private bool _shouldGenerateCommonParameters;594 595        /// <summary>596        /// Gets or sets the obsolete attribute on the command.597        /// </summary>598        /// <value></value>599        internal ObsoleteAttribute Obsolete { get; set; }600 601        #endregion602 603        #region internal members604 605        /// <summary>606        /// Gets the merged metadata for the command including cmdlet declared parameters,607        /// common parameters, and (optionally) ShouldProcess and Transactions parameters.608        /// </summary>609        /// <value></value>610        internal MergedCommandParameterMetadata StaticCommandParameterMetadata611        {612            get613            {614                return _staticCommandParameterMetadata;615            }616        }617 618        private readonly MergedCommandParameterMetadata _staticCommandParameterMetadata;619 620        /// <summary>621        /// True if the cmdlet implements dynamic parameters, or false otherwise.622        /// </summary>623        /// <value></value>624        internal bool ImplementsDynamicParameters625        {626            get { return _implementsDynamicParameters; }627        }628 629        private bool _implementsDynamicParameters;630 631        /// <summary>632        /// Gets the bit in the parameter set map for the default parameter set.633        /// </summary>634        internal uint DefaultParameterSetFlag635        {636            get { return _defaultParameterSetFlag; }637 638            set { _defaultParameterSetFlag = value; }639        }640 641        private uint _defaultParameterSetFlag;642 643        /// <summary>644        /// A collection of attributes that were declared at the cmdlet level but were not645        /// recognized by the engine.646        /// </summary>647        private readonly Collection<Attribute> _otherAttributes = new Collection<Attribute>();648 649        // command this CommandMetadata instance is intended to wrap650        private string _wrappedCommand;651        // the type of command this CommandMetadata instance is intended to wrap652        private CommandTypes _wrappedCommandType;653        // The CommandType for a script cmdlet is not CommandTypes.Cmdlet, yet654        // proxy generation needs to know the difference between script and script cmdlet.655        private bool _wrappedAnyCmdlet;656 657        internal bool WrappedAnyCmdlet658        {659            get { return _wrappedAnyCmdlet; }660        }661 662        internal CommandTypes WrappedCommandType663        {664            get665            {666                return _wrappedCommandType;667            }668        }669 670        #endregion internal members671 672        #region helper methods673 674        /// <summary>675        /// Constructs the command metadata by using reflection against the676        /// CLR type.677        /// </summary>678        /// <exception cref="ParsingMetadataException">679        /// If more than int.MaxValue parameter-sets are defined for the command.680        /// </exception>681        private void ConstructCmdletMetadataUsingReflection()682        {683            Diagnostics.Assert(684                CommandType != null,685                "This method should only be called when constructed with the Type");686 687            // Determine if the cmdlet implements dynamic parameters by looking for the interface688 689            Type dynamicParametersType = CommandType.GetInterface(nameof(IDynamicParameters), true);690 691            if (dynamicParametersType != null)692            {693                _implementsDynamicParameters = true;694            }695 696            // Process the attributes on the cmdlet697 698            var customAttributes = CommandType.GetCustomAttributes(false);699 700            foreach (Attribute attribute in customAttributes)701            {702                CmdletAttribute cmdletAttribute = attribute as CmdletAttribute;703                if (cmdletAttribute != null)704                {705                    ProcessCmdletAttribute(cmdletAttribute);706                    this.Name = cmdletAttribute.VerbName + "-" + cmdletAttribute.NounName;707                }708                else if (attribute is ObsoleteAttribute)709                {710                    Obsolete = (ObsoleteAttribute)attribute;711                }712                else713                {714                    _otherAttributes.Add(attribute);715                }716            }717        }718 719        /// <summary>720        /// Extracts the cmdlet data from the CmdletAttribute.721        /// </summary>722        /// <param name="attribute">723        /// The CmdletAttribute to process724        /// </param>725        /// <exception cref="ArgumentNullException">726        /// If <paramref name="attribute"/> is null.727        /// </exception>728        /// <exception cref="ParsingMetadataException">729        /// If more than int.MaxValue parameter-sets are defined for the command.730        /// </exception>731        private void ProcessCmdletAttribute(CmdletCommonMetadataAttribute attribute)732        {733            if (attribute == null)734            {735                throw PSTraceSource.NewArgumentNullException(nameof(attribute));736            }737 738            // Process the default parameter set name739            _defaultParameterSetName = attribute.DefaultParameterSetName;740 741            // Check to see if the cmdlet supports ShouldProcess742            SupportsShouldProcess = attribute.SupportsShouldProcess;743 744            // Determine the cmdlet's impact confirmation745            ConfirmImpact = attribute.ConfirmImpact;746 747            // Check to see if the cmdlet supports paging748            SupportsPaging = attribute.SupportsPaging;749 750            // Check to see if the cmdlet supports transactions751            SupportsTransactions = attribute.SupportsTransactions;752 753            // Grab related link754            HelpUri = attribute.HelpUri;755 756            // Remoting support757            _remotingCapability = attribute.RemotingCapability;758 759            // Check to see if the cmdlet uses positional binding760            var cmdletBindingAttribute = attribute as CmdletBindingAttribute;761            if (cmdletBindingAttribute != null)762            {763                PositionalBinding = cmdletBindingAttribute.PositionalBinding;764            }765        }766 767        /// <summary>768        /// Merges parameter metadata from different sources: those that are coming from Type,769        /// CommonParameters, should process etc.770        /// </summary>771        /// <param name="context"></param>772        /// <param name="parameterMetadata"></param>773        /// <param name="shouldGenerateCommonParameters">774        /// true if metadata info about Verbose,Debug etc needs to be generated.775        /// false otherwise.776        /// </param>777        private MergedCommandParameterMetadata MergeParameterMetadata(ExecutionContext context, InternalParameterMetadata parameterMetadata, bool shouldGenerateCommonParameters)778        {779            // Create an instance of the static metadata class780            MergedCommandParameterMetadata staticCommandParameterMetadata =781                new MergedCommandParameterMetadata();782 783            // First add the metadata for the formal cmdlet parameters784            staticCommandParameterMetadata.AddMetadataForBinder(785                parameterMetadata,786                ParameterBinderAssociation.DeclaredFormalParameters);787 788            // Now add the common parameters metadata789            if (shouldGenerateCommonParameters)790            {791                InternalParameterMetadata commonParametersMetadata =792                    InternalParameterMetadata.Get(typeof(CommonParameters), context, false);793 794                staticCommandParameterMetadata.AddMetadataForBinder(795                    commonParametersMetadata,796                    ParameterBinderAssociation.CommonParameters);797 798                // If the command supports ShouldProcess, add the metadata for799                // those parameters800                if (this.SupportsShouldProcess)801                {802                    InternalParameterMetadata shouldProcessParametersMetadata =803                        InternalParameterMetadata.Get(typeof(ShouldProcessParameters), context, false);804 805                    staticCommandParameterMetadata.AddMetadataForBinder(806                        shouldProcessParametersMetadata,807                        ParameterBinderAssociation.ShouldProcessParameters);808                }809 810                // If the command supports paging, add the metadata for811                // those parameters812                if (this.SupportsPaging)813                {814                    InternalParameterMetadata pagingParametersMetadata =815                        InternalParameterMetadata.Get(typeof(PagingParameters), context, false);816 817                    staticCommandParameterMetadata.AddMetadataForBinder(818                        pagingParametersMetadata,819                        ParameterBinderAssociation.PagingParameters);820                }821 822                // If the command supports transactions, add the metadata for823                // those parameters824                if (this.SupportsTransactions)825                {826                    InternalParameterMetadata transactionParametersMetadata =827                        InternalParameterMetadata.Get(typeof(TransactionParameters), context, false);828 829                    staticCommandParameterMetadata.AddMetadataForBinder(830                        transactionParametersMetadata,831                        ParameterBinderAssociation.TransactionParameters);832                }833            }834 835            return staticCommandParameterMetadata;836        }837 838        #endregion helper methods839 840        #region Proxy Command generation841 842        /// <summary>843        /// Gets the ScriptCmdlet in string format.844        /// </summary>845        /// <returns></returns>846        internal string GetProxyCommand(string helpComment, bool generateDynamicParameters)847        {848            if (string.IsNullOrEmpty(helpComment))849            {850                helpComment = string.Create(CultureInfo.InvariantCulture, $@"851.ForwardHelpTargetName {_wrappedCommand}852.ForwardHelpCategory {_wrappedCommandType}853");854            }855 856            string dynamicParamblock = string.Empty;857            if (generateDynamicParameters && this.ImplementsDynamicParameters)858            {859                dynamicParamblock = string.Create(CultureInfo.InvariantCulture, $@"860dynamicparam861{{{GetDynamicParamBlock()}}}862 863");864            }865 866            string result = string.Create(CultureInfo.InvariantCulture, $@"{GetDecl()}867param({GetParamBlock()})868 869{dynamicParamblock}begin870{{{GetBeginBlock()}}}871 872process873{{{GetProcessBlock()}}}874 875end876{{{GetEndBlock()}}}877 878clean879{{{GetCleanBlock()}}}880<#881{CodeGeneration.EscapeBlockCommentContent(helpComment)}882#>883");884 885            return result;886        }887 888        internal string GetDecl()889        {890            string result = string.Empty;891            string separator = string.Empty;892            if (_wrappedAnyCmdlet)893            {894                StringBuilder decl = new StringBuilder("[CmdletBinding(");895 896                if (!string.IsNullOrEmpty(_defaultParameterSetName))897                {898                    decl.Append(separator);899                    decl.Append("DefaultParameterSetName='");900                    decl.Append(CodeGeneration.EscapeSingleQuotedStringContent(_defaultParameterSetName));901                    decl.Append('\'');902                    separator = ", ";903                }904 905                if (SupportsShouldProcess)906                {907                    decl.Append(separator);908                    decl.Append("SupportsShouldProcess=$true");909                    separator = ", ";910                    decl.Append(separator);911                    decl.Append("ConfirmImpact='");912                    decl.Append(ConfirmImpact);913                    decl.Append('\'');914                }915 916                if (SupportsPaging)917                {918                    decl.Append(separator);919                    decl.Append("SupportsPaging=$true");920                    separator = ", ";921                }922 923                if (SupportsTransactions)924                {925                    decl.Append(separator);926                    decl.Append("SupportsTransactions=$true");927                    separator = ", ";928                }929 930                if (!PositionalBinding)931                {932                    decl.Append(separator);933                    decl.Append("PositionalBinding=$false");934                    separator = ", ";935                }936 937                if (!string.IsNullOrEmpty(HelpUri))938                {939                    decl.Append(separator);940                    decl.Append("HelpUri='");941                    decl.Append(CodeGeneration.EscapeSingleQuotedStringContent(HelpUri));942                    decl.Append('\'');943                    separator = ", ";944                }945 946                if (_remotingCapability != RemotingCapability.PowerShell)947                {948                    decl.Append(separator);949                    decl.Append("RemotingCapability='");950                    decl.Append(_remotingCapability);951                    decl.Append('\'');952                    separator = ", ";953                }954 955                decl.Append(")]");956 957                result = decl.ToString();958            }959 960            return result;961        }962 963        internal string GetParamBlock()964        {965            if (Parameters.Keys.Count > 0)966            {967                StringBuilder parameters = new StringBuilder();968                string prefix = string.Concat(Environment.NewLine, "    ");969                string paramDataPrefix = null;970 971                foreach (var pair in Parameters)972                {973                    if (paramDataPrefix != null)974                    {975                        parameters.Append(paramDataPrefix);976                    }977                    else978                    {979                        // syntax for parameter separation : comma followed by new-line.980                        paramDataPrefix = string.Concat(",", Environment.NewLine);981                    }982                    // generate the parameter proxy and append to the list983                    string paramData = pair.Value.GetProxyParameterData(prefix, pair.Key, _wrappedAnyCmdlet);984                    parameters.Append(paramData);985                }986 987                return parameters.ToString();988            }989 990            return string.Empty;991        }992 993        internal string GetBeginBlock()994        {995            string result;996 997            if (string.IsNullOrEmpty(_wrappedCommand))998            {999                string error = ProxyCommandStrings.CommandMetadataMissingCommandName;1000                throw new InvalidOperationException(error);1001            }1002 1003            string commandOrigin = "$myInvocation.CommandOrigin";1004 1005            // For functions, don't proxy the command origin, otherwise they will1006            // be subject to the runspace restrictions1007            if (_wrappedCommandType == CommandTypes.Function)1008            {1009                commandOrigin = string.Empty;1010            }1011 1012            string wrappedCommand = CodeGeneration.EscapeSingleQuotedStringContent(_wrappedCommand);1013            if (_wrappedAnyCmdlet)1014            {1015                result = string.Create(CultureInfo.InvariantCulture, $@"1016    try {{1017        $outBuffer = $null1018        if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))1019        {{1020            $PSBoundParameters['OutBuffer'] = 11021        }}1022 1023        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('{wrappedCommand}', [System.Management.Automation.CommandTypes]::{_wrappedCommandType})1024        $scriptCmd = {{& $wrappedCmd @PSBoundParameters }}1025 1026        $steppablePipeline = $scriptCmd.GetSteppablePipeline({commandOrigin})1027        $steppablePipeline.Begin($PSCmdlet)1028    }} catch {{1029        throw1030    }}1031");1032            }1033            else1034            {1035                result = string.Create(CultureInfo.InvariantCulture, $@"1036    try {{1037        $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('{wrappedCommand}', [System.Management.Automation.CommandTypes]::{_wrappedCommandType})1038        $PSBoundParameters.Add('$args', $args)1039        $scriptCmd = {{& $wrappedCmd @PSBoundParameters }}1040 1041        $steppablePipeline = $scriptCmd.GetSteppablePipeline({commandOrigin})1042        $steppablePipeline.Begin($myInvocation.ExpectingInput, $ExecutionContext)1043    }} catch {{1044        throw1045    }}1046");1047            }1048 1049            return result;1050        }1051 1052        internal string GetProcessBlock()1053        {1054            // The reason we wrap scripts in 'try { } catch { throw }' (here and elsewhere) is to turn1055            // an exception that could be thrown from .NET method invocation into a terminating error1056            // that can be propagated up.1057            // By default, an exception thrown from .NET method is not terminating, but when enclosed1058            // in try/catch, it will be turned into a terminating error.1059            return @"1060    try {1061        $steppablePipeline.Process($_)1062    } catch {1063        throw1064    }1065";1066        }1067 1068        internal string GetDynamicParamBlock()1069        {1070            string wrappedCommand = CodeGeneration.EscapeSingleQuotedStringContent(_wrappedCommand);1071            return string.Create(CultureInfo.InvariantCulture, $@"1072    try {{1073        $targetCmd = $ExecutionContext.InvokeCommand.GetCommand('{wrappedCommand}', [System.Management.Automation.CommandTypes]::{_wrappedCommandType}, $PSBoundParameters)1074        $dynamicParams = @($targetCmd.Parameters.GetEnumerator() | Microsoft.PowerShell.Core\Where-Object {{ $_.Value.IsDynamic }})1075        if ($dynamicParams.Length -gt 0)1076        {{1077            $paramDictionary = [Management.Automation.RuntimeDefinedParameterDictionary]::new()1078            foreach ($param in $dynamicParams)1079            {{1080                $param = $param.Value1081 1082                if(-not $MyInvocation.MyCommand.Parameters.ContainsKey($param.Name))1083                {{1084                    $dynParam = [Management.Automation.RuntimeDefinedParameter]::new($param.Name, $param.ParameterType, $param.Attributes)1085                    $paramDictionary.Add($param.Name, $dynParam)1086                }}1087            }}1088 1089            return $paramDictionary1090        }}1091    }} catch {{1092        throw1093    }}1094");1095        }1096 1097        internal string GetEndBlock()1098        {1099            return @"1100    try {1101        $steppablePipeline.End()1102    } catch {1103        throw1104    }1105";1106        }1107 1108        internal string GetCleanBlock()1109        {1110            // Here we don't need to enclose the script in a 'try/catch' like elsewhere, because1111            //  1. the 'Clean' block doesn't propagate up any exception (terminating error);1112            //  2. only one expression in the script, so nothing else needs to be stopped when invoking the method fails.1113            return @"1114    if ($null -ne $steppablePipeline) {1115        $steppablePipeline.Clean()1116    }1117";1118        }1119 1120        #endregion1121 1122        #region Helper methods for restricting commands needed by implicit and interactive remoting1123 1124        internal const string isSafeNameOrIdentifierRegex = @"^[-._:\\\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}\p{Lm}]{1,100}$";1125 1126        private static CommandMetadata GetRestrictedCmdlet(string cmdletName, string defaultParameterSet, string helpUri, params ParameterMetadata[] parameters)1127        {1128            Dictionary<string, ParameterMetadata> parametersDictionary = new Dictionary<string, ParameterMetadata>(StringComparer.OrdinalIgnoreCase);1129            foreach (ParameterMetadata parameter in parameters)1130            {1131                parametersDictionary.Add(parameter.Name, parameter);1132            }1133 1134            // isProxyForCmdlet:1135            // 1a. we would want to set it to false to get rid of unused common parameters1136            //    (like OutBuffer - see bug Windows 7: #402213)1137            // 1b. otoh common parameters are going to be present anyway on all proxy functions1138            //     that the host generates for its cmdlets that need cmdletbinding, so1139            //     we should make sure that common parameters are safe, not hide them1140            // 2. otoh without cmdletbinding() unspecified parameters get bound to $null which might1141            //    unnecessarily trigger validation attribute failures - see bug Windows 7: #4772181142 1143            CommandMetadata metadata = new CommandMetadata(1144                                   name: cmdletName,1145                            commandType: CommandTypes.Cmdlet,1146                       isProxyForCmdlet: true,1147                defaultParameterSetName: defaultParameterSet,1148                  supportsShouldProcess: false,1149                          confirmImpact: ConfirmImpact.None,1150                         supportsPaging: false,1151                   supportsTransactions: false,1152                      positionalBinding: true,1153                             parameters: parametersDictionary);1154 1155            metadata.HelpUri = helpUri;1156 1157            return metadata;1158        }1159 1160        private static CommandMetadata GetRestrictedGetCommand()1161        {1162            // remote Get-Command called by Import/Export-PSSession to get metadata for remote commands that user wants to import1163 1164            // remote Get-Command is also called by interactive remoting before entering the remote session to verify1165            // that Out-Default and Exit-PSSession commands are present in the remote session1166 1167            // value passed directly from Import-PSSession -CommandName to Get-Command -Name1168            // can't really restrict beyond basics1169            ParameterMetadata nameParameter = new ParameterMetadata("Name", typeof(string[]));1170            nameParameter.Attributes.Add(new ValidateLengthAttribute(0, 1000));1171            nameParameter.Attributes.Add(new ValidateCountAttribute(0, 1000));1172 1173            // value passed directly from Import-PSSession -PSSnapIn to Get-Command -Module1174            // can't really restrict beyond basics1175            ParameterMetadata moduleParameter = new ParameterMetadata("Module", typeof(string[]));1176            moduleParameter.Attributes.Add(new ValidateLengthAttribute(0, 1000));1177            moduleParameter.Attributes.Add(new ValidateCountAttribute(0, 100));1178 1179            // value passed directly from Import-PSSession -ArgumentList to Get-Command -ArgumentList1180            // can't really restrict beyond basics1181            ParameterMetadata argumentListParameter = new ParameterMetadata("ArgumentList", typeof(object[]));1182            argumentListParameter.Attributes.Add(new ValidateCountAttribute(0, 100));1183 1184            // value passed directly from Import-PSSession -CommandType to Get-Command -CommandType1185            // can't really restrict beyond basics1186            ParameterMetadata commandTypeParameter = new ParameterMetadata("CommandType", typeof(CommandTypes));1187 1188            // we do allow -ListImported switch1189            ParameterMetadata listImportedParameter = new ParameterMetadata("ListImported", typeof(SwitchParameter));1190 1191            // Need to expose ShowCommandInfo parameter for remote ShowCommand support.1192            ParameterMetadata showCommandInfo = new ParameterMetadata("ShowCommandInfo", typeof(SwitchParameter));1193 1194            return GetRestrictedCmdlet(1195                "Get-Command",1196                null, // defaultParameterSet1197                "https://go.microsoft.com/fwlink/?LinkID=113309", // helpUri1198                nameParameter,1199                moduleParameter,1200                argumentListParameter,

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