Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
FormatViewManager.cs686 linesDownload Raw Back to common
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System;5using System.Collections.Generic;6using System.Collections.ObjectModel;7using System.Management.Automation;8using System.Management.Automation.Internal;9using System.Text;10 11using Microsoft.PowerShell.Commands;12 13namespace Microsoft.PowerShell.Commands.Internal.Format14{15    internal static class DefaultScalarTypes16    {17        internal static bool IsTypeInList(Collection<string> typeNames)18        {19            // NOTE: we do not use inheritance here, since we deal with20            // value types or with types where inheritance is not a factor for the selection21            string typeName = PSObjectHelper.PSObjectIsOfExactType(typeNames);22 23            if (string.IsNullOrEmpty(typeName))24                return false;25 26            string originalTypeName = Deserializer.MaskDeserializationPrefix(typeName);27 28            if (string.IsNullOrEmpty(originalTypeName))29                return false;30 31            // check if the type is derived from a System.Enum32            // e.g. in C#33            // enum Foo { Red, Black, Green}34 35            if (PSObjectHelper.PSObjectIsEnum(typeNames))36                return true;37 38            return s_defaultScalarTypesHash.Contains(originalTypeName);39        }40 41        static DefaultScalarTypes()42        {43            s_defaultScalarTypesHash.Add("System.String");44            s_defaultScalarTypesHash.Add("System.SByte");45            s_defaultScalarTypesHash.Add("System.Byte");46            s_defaultScalarTypesHash.Add("System.Int16");47            s_defaultScalarTypesHash.Add("System.UInt16");48            s_defaultScalarTypesHash.Add("System.Int32");49            s_defaultScalarTypesHash.Add("System.UInt32");50            s_defaultScalarTypesHash.Add("System.Int64");51            s_defaultScalarTypesHash.Add("System.UInt64");52            s_defaultScalarTypesHash.Add("System.Char");53            s_defaultScalarTypesHash.Add("System.Single");54            s_defaultScalarTypesHash.Add("System.Double");55            s_defaultScalarTypesHash.Add("System.Boolean");56            s_defaultScalarTypesHash.Add("System.Decimal");57            s_defaultScalarTypesHash.Add("System.IntPtr");58            s_defaultScalarTypesHash.Add("System.Security.SecureString");59            s_defaultScalarTypesHash.Add("System.Numerics.BigInteger");60        }61 62        private static readonly HashSet<string> s_defaultScalarTypesHash = new HashSet<string>(StringComparer.OrdinalIgnoreCase);63    }64 65    /// <summary>66    /// Class to manage the selection of a desired view type and67    /// manage state associated to the selected view.68    /// </summary>69    internal sealed class FormatViewManager70    {71        #region tracer72        [TraceSource("FormatViewBinding", "Format view binding")]73        private static readonly PSTraceSource s_formatViewBindingTracer = PSTraceSource.GetTracer("FormatViewBinding", "Format view binding", false);74        #endregion tracer75 76        private static string PSObjectTypeName(PSObject so)77        {78            // if so is not null, its TypeNames will not be null79            if (so != null)80            {81                var typeNames = so.InternalTypeNames;82                if (typeNames.Count > 0)83                {84                    return typeNames[0];85                }86            }87 88            return string.Empty;89        }90 91        internal void Initialize(TerminatingErrorContext errorContext,92                                    PSPropertyExpressionFactory expressionFactory,93                                    TypeInfoDataBase db,94                                    PSObject so,95                                    FormatShape shape,96                                    FormattingCommandLineParameters parameters)97        {98            ViewDefinition view = null;99            const string findViewType = "FINDING VIEW TYPE: {0}";100            const string findViewShapeType = "FINDING VIEW {0} TYPE: {1}";101            const string findViewNameType = "FINDING VIEW NAME: {0} TYPE: {1}";102            const string viewFound = "An applicable view has been found";103            const string viewNotFound = "No applicable view has been found";104            try105            {106                DisplayDataQuery.SetTracer(s_formatViewBindingTracer);107 108                // shape not specified: we need to select one109                var typeNames = so.InternalTypeNames;110                if (shape == FormatShape.Undefined)111                {112                    using (s_formatViewBindingTracer.TraceScope(findViewType, PSObjectTypeName(so)))113                    {114                        view = DisplayDataQuery.GetViewByShapeAndType(expressionFactory, db, shape, typeNames, null);115                    }116 117                    if (view != null)118                    {119                        // we got a matching view from the database120                        // use this and we are done121                        _viewGenerator = SelectViewGeneratorFromViewDefinition(122                                                errorContext,123                                                expressionFactory,124                                                db,125                                                view,126                                                parameters);127                        s_formatViewBindingTracer.WriteLine(viewFound);128                        PrepareViewForRemoteObjects(ViewGenerator, so);129                        return;130                    }131 132                    s_formatViewBindingTracer.WriteLine(viewNotFound);133                    // we did not get any default view (and shape), we need to force one134                    // we just select properties out of the object itself, since they were not135                    // specified on the command line136                    _viewGenerator = SelectViewGeneratorFromProperties(shape, so, errorContext, expressionFactory, db, null);137                    PrepareViewForRemoteObjects(ViewGenerator, so);138 139                    return;140                }141 142                // we have a predefined shape: did the user specify properties on the command line?143                if (parameters != null && parameters.mshParameterList.Count > 0)144                {145                    _viewGenerator = SelectViewGeneratorFromProperties(shape, so, errorContext, expressionFactory, db, parameters);146                    return;147                }148 149                // predefined shape: did the user specify the name of a view?150                if (parameters != null && !string.IsNullOrEmpty(parameters.viewName))151                {152                    using (s_formatViewBindingTracer.TraceScope(findViewNameType, parameters.viewName,153                        PSObjectTypeName(so)))154                    {155                        view = DisplayDataQuery.GetViewByShapeAndType(expressionFactory, db, shape, typeNames, parameters.viewName);156                    }157 158                    if (view != null)159                    {160                        _viewGenerator = SelectViewGeneratorFromViewDefinition(161                                                    errorContext,162                                                    expressionFactory,163                                                    db,164                                                    view,165                                                    parameters);166                        s_formatViewBindingTracer.WriteLine(viewFound);167                        return;168                    }169 170                    s_formatViewBindingTracer.WriteLine(viewNotFound);171                    // illegal input, we have to terminate172                    ProcessUnknownViewName(errorContext, parameters.viewName, so, db, shape);173                }174 175                // predefined shape: do we have a default view in format.ps1xml?176                using (s_formatViewBindingTracer.TraceScope(findViewShapeType, shape, PSObjectTypeName(so)))177                {178                    view = DisplayDataQuery.GetViewByShapeAndType(expressionFactory, db, shape, typeNames, null);179                }180 181                if (view != null)182                {183                    _viewGenerator = SelectViewGeneratorFromViewDefinition(184                                                errorContext,185                                                expressionFactory,186                                                db,187                                                view,188                                                parameters);189                    s_formatViewBindingTracer.WriteLine(viewFound);190                    PrepareViewForRemoteObjects(ViewGenerator, so);191 192                    return;193                }194 195                s_formatViewBindingTracer.WriteLine(viewNotFound);196                // we just select properties out of the object itself197                _viewGenerator = SelectViewGeneratorFromProperties(shape, so, errorContext, expressionFactory, db, parameters);198                PrepareViewForRemoteObjects(ViewGenerator, so);199            }200            finally201            {202                DisplayDataQuery.ResetTracer();203            }204        }205 206        /// <summary>207        /// Prepares a given view for remote object processing ie., lets the view208        /// display (or not) ComputerName property. This will query the object to209        /// check if ComputerName property is present. If present, this will prepare210        /// the view.211        /// </summary>212        /// <param name="viewGenerator"></param>213        /// <param name="so"></param>214        private static void PrepareViewForRemoteObjects(ViewGenerator viewGenerator, PSObject so)215        {216            if (PSObjectHelper.ShouldShowComputerNameProperty(so))217            {218                viewGenerator.PrepareForRemoteObjects(so);219            }220        }221 222        /// <summary>223        /// Helper method to process Unknown error message.224        /// It helps is creating appropriate error message to225        /// be displayed to the user.226        /// </summary>227        /// <param name="errorContext">Error context.</param>228        /// <param name="viewName">Uses supplied view name.</param>229        /// <param name="so">Source object.</param>230        /// <param name="db">Types info database.</param>231        /// <param name="formatShape">Requested format shape.</param>232        private static void ProcessUnknownViewName(TerminatingErrorContext errorContext, string viewName, PSObject so, TypeInfoDataBase db, FormatShape formatShape)233        {234            string msg = null;235            bool foundValidViews = false;236            string formatTypeName = null;237            const string separator = ", ";238            StringBuilder validViewFormats = new StringBuilder();239 240            if (so != null && so.BaseObject != null &&241                db != null && db.viewDefinitionsSection != null &&242                db.viewDefinitionsSection.viewDefinitionList != null &&243                db.viewDefinitionsSection.viewDefinitionList.Count > 0)244            {245                StringBuilder validViews = new StringBuilder();246                string currentObjectTypeName = so.BaseObject.GetType().ToString();247 248                Type formatType = null;249                if (formatShape == FormatShape.Table)250                {251                    formatType = typeof(TableControlBody);252                    formatTypeName = "Table";253                }254                else if (formatShape == FormatShape.List)255                {256                    formatType = typeof(ListControlBody);257                    formatTypeName = "List";258                }259                else if (formatShape == FormatShape.Wide)260                {261                    formatType = typeof(WideControlBody);262                    formatTypeName = "Wide";263                }264                else if (formatShape == FormatShape.Complex)265                {266                    formatType = typeof(ComplexControlBody);267                    formatTypeName = "Custom";268                }269 270                if (formatType != null)271                {272                    foreach (ViewDefinition currentViewDefinition in db.viewDefinitionsSection.viewDefinitionList)273                    {274                        if (currentViewDefinition.mainControl != null)275                        {276                            foreach (TypeOrGroupReference currentTypeOrGroupReference in currentViewDefinition.appliesTo.referenceList)277                            {278                                if (!string.IsNullOrEmpty(currentTypeOrGroupReference.name) &&279                                    string.Equals(currentObjectTypeName, currentTypeOrGroupReference.name, StringComparison.OrdinalIgnoreCase))280                                {281                                    if (currentViewDefinition.mainControl.GetType() == formatType)282                                    {283                                        validViews.Append(currentViewDefinition.name);284                                        validViews.Append(separator);285                                    }286                                    else if (string.Equals(viewName, currentViewDefinition.name, StringComparison.OrdinalIgnoreCase))287                                    {288                                        string cmdletFormatName = null;289                                        if (currentViewDefinition.mainControl is TableControlBody)290                                        {291                                            cmdletFormatName = "Format-Table";292                                        }293                                        else if (currentViewDefinition.mainControl is ListControlBody)294                                        {295                                            cmdletFormatName = "Format-List";296                                        }297                                        else if (currentViewDefinition.mainControl is WideControlBody)298                                        {299                                            cmdletFormatName = "Format-Wide";300                                        }301                                        else if (currentViewDefinition.mainControl is ComplexControlBody)302                                        {303                                            cmdletFormatName = "Format-Custom";304                                        }305 306                                        if (validViewFormats.Length == 0)307                                        {308                                            string suggestValidViewNamePrefix = StringUtil.Format(FormatAndOut_format_xxx.SuggestValidViewNamePrefix);309                                            validViewFormats.Append(suggestValidViewNamePrefix);310                                        }311                                        else312                                        {313                                            validViewFormats.Append(", ");314                                        }315 316                                        validViewFormats.Append(cmdletFormatName);317                                    }318                                }319                            }320                        }321                    }322                }323 324                if (validViews.Length > 0)325                {326                    validViews.Remove(validViews.Length - separator.Length, separator.Length);327                    msg = StringUtil.Format(FormatAndOut_format_xxx.InvalidViewNameError, viewName, formatTypeName, validViews.ToString());328                    foundValidViews = true;329                }330            }331 332            if (!foundValidViews)333            {334                StringBuilder unKnowViewFormatStringBuilder = new StringBuilder();335                if (validViewFormats.Length > 0)336                {337                    // unKnowViewFormatStringBuilder.Append(StringUtil.Format(FormatAndOut_format_xxx.UnknownViewNameError, viewName));338                    unKnowViewFormatStringBuilder.Append(StringUtil.Format(FormatAndOut_format_xxx.UnknownViewNameErrorSuffix, viewName, formatTypeName));339                    unKnowViewFormatStringBuilder.Append(validViewFormats);340                }341                else342                {343                    unKnowViewFormatStringBuilder.Append(StringUtil.Format(FormatAndOut_format_xxx.UnknownViewNameError, viewName));344                    unKnowViewFormatStringBuilder.Append(StringUtil.Format(FormatAndOut_format_xxx.NonExistingViewNameError, formatTypeName, so.BaseObject.GetType()));345                }346 347                msg = unKnowViewFormatStringBuilder.ToString();348            }349 350            ErrorRecord errorRecord = new ErrorRecord(351                                            new PipelineStoppedException(),352                                            "FormatViewNotFound",353                                            ErrorCategory.ObjectNotFound,354                                            viewName);355 356            errorRecord.ErrorDetails = new ErrorDetails(msg);357            errorContext.ThrowTerminatingError(errorRecord);358        }359 360        internal ViewGenerator ViewGenerator361        {362            get363            {364                Diagnostics.Assert(_viewGenerator != null, "this.viewGenerator cannot be null");365                return _viewGenerator;366            }367        }368 369        private static ViewGenerator SelectViewGeneratorFromViewDefinition(370                                        TerminatingErrorContext errorContext,371                                        PSPropertyExpressionFactory expressionFactory,372                                        TypeInfoDataBase db,373                                        ViewDefinition view,374                                        FormattingCommandLineParameters parameters)375        {376            ViewGenerator viewGenerator = null;377            if (view.mainControl is TableControlBody)378            {379                viewGenerator = new TableViewGenerator();380            }381            else if (view.mainControl is ListControlBody)382            {383                viewGenerator = new ListViewGenerator();384            }385            else if (view.mainControl is WideControlBody)386            {387                viewGenerator = new WideViewGenerator();388            }389            else if (view.mainControl is ComplexControlBody)390            {391                viewGenerator = new ComplexViewGenerator();392            }393 394            Diagnostics.Assert(viewGenerator != null, "viewGenerator != null");395            viewGenerator.Initialize(errorContext, expressionFactory, db, view, parameters);396            return viewGenerator;397        }398 399        private static ViewGenerator SelectViewGeneratorFromProperties(FormatShape shape, PSObject so,400                                    TerminatingErrorContext errorContext,401                                    PSPropertyExpressionFactory expressionFactory,402                                    TypeInfoDataBase db,403                                    FormattingCommandLineParameters parameters)404        {405            // use some heuristics to determine the shape if none is specified406            if (shape == FormatShape.Undefined && parameters == null)407            {408                // check first if we have a known shape for a type409                var typeNames = so.InternalTypeNames;410                shape = DisplayDataQuery.GetShapeFromType(expressionFactory, db, typeNames);411 412                if (shape == FormatShape.Undefined)413                {414                    // check if we can have a table:415                    // we want to get the # of properties we are going to display416                    List<PSPropertyExpression> expressionList = PSObjectHelper.GetDefaultPropertySet(so);417                    if (expressionList.Count == 0)418                    {419                        // we failed to get anything from a property set420                        // we just get the first properties out of the first object421                        foreach (MshResolvedExpressionParameterAssociation mrepa in AssociationManager.ExpandAll(so))422                        {423                            expressionList.Add(mrepa.ResolvedExpression);424                        }425                    }426 427                    // decide what shape we want for the given number of properties428                    shape = DisplayDataQuery.GetShapeFromPropertyCount(db, expressionList.Count);429                }430            }431 432            ViewGenerator viewGenerator = null;433            if (shape == FormatShape.Table)434            {435                viewGenerator = new TableViewGenerator();436            }437            else if (shape == FormatShape.List)438            {439                viewGenerator = new ListViewGenerator();440            }441            else if (shape == FormatShape.Wide)442            {443                viewGenerator = new WideViewGenerator();444            }445            else if (shape == FormatShape.Complex)446            {447                viewGenerator = new ComplexViewGenerator();448            }449 450            Diagnostics.Assert(viewGenerator != null, "viewGenerator != null");451 452            viewGenerator.Initialize(errorContext, expressionFactory, so, db, parameters);453            return viewGenerator;454        }455 456        /// <summary>457        /// The view generator that produced data for a selected shape.458        /// </summary>459        private ViewGenerator _viewGenerator = null;460    }461 462    /// <summary>463    /// Class to manage the selection of a desired view type464    /// for out of band objects.465    /// </summary>466    internal static class OutOfBandFormatViewManager467    {468        private static bool IsNotRemotingProperty(string name)469        {470            var isRemotingPropertyName = name.Equals(RemotingConstants.ComputerNameNoteProperty, StringComparison.OrdinalIgnoreCase)471                   || name.Equals(RemotingConstants.ShowComputerNameNoteProperty, StringComparison.OrdinalIgnoreCase)472                   || name.Equals(RemotingConstants.RunspaceIdNoteProperty, StringComparison.OrdinalIgnoreCase)473                   || name.Equals(RemotingConstants.SourceJobInstanceId, StringComparison.OrdinalIgnoreCase);474            return !isRemotingPropertyName;475        }476 477        private static readonly MemberNamePredicate NameIsNotRemotingProperty = IsNotRemotingProperty;478 479        internal static bool HasNonRemotingProperties(PSObject so) => so.GetFirstPropertyOrDefault(NameIsNotRemotingProperty) != null;480 481        internal static FormatEntryData GenerateOutOfBandData(TerminatingErrorContext errorContext, PSPropertyExpressionFactory expressionFactory,482                    TypeInfoDataBase db, PSObject so, int enumerationLimit, bool useToStringFallback, out List<ErrorRecord> errors)483        {484            errors = null;485 486            var typeNames = so.InternalTypeNames;487            ViewDefinition view = DisplayDataQuery.GetOutOfBandView(expressionFactory, db, typeNames);488 489            ViewGenerator outOfBandViewGenerator;490            if (view != null)491            {492                // process an out of band view retrieved from the display database493                if (view.mainControl is ComplexControlBody)494                {495                    outOfBandViewGenerator = new ComplexViewGenerator();496                }497                else498                {499                    outOfBandViewGenerator = new ListViewGenerator();500                }501 502                outOfBandViewGenerator.Initialize(errorContext, expressionFactory, db, view, null);503            }504            else505            {506                if (DefaultScalarTypes.IsTypeInList(typeNames)507                    || !HasNonRemotingProperties(so))508                {509                    // we force a ToString() on well known types510                    return GenerateOutOfBandObjectAsToString(so);511                }512 513                if (!useToStringFallback)514                {515                    return null;516                }517 518                // we must check we have enough properties for a list view519                if (new PSPropertyExpression("*").ResolveNames(so).Count == 0)520                {521                    return null;522                }523 524                // we do not have a view, we default to list view525                // process an out of band view as a default526                outOfBandViewGenerator = new ListViewGenerator();527                outOfBandViewGenerator.Initialize(errorContext, expressionFactory, so, db, null);528            }529 530            FormatEntryData fed = outOfBandViewGenerator.GeneratePayload(so, enumerationLimit);531            fed.outOfBand = true;532            fed.writeStream = so.WriteStream;533 534            errors = outOfBandViewGenerator.ErrorManager.DrainFailedResultList();535 536            return fed;537        }538 539        internal static FormatEntryData GenerateOutOfBandObjectAsToString(PSObject so)540        {541            FormatEntryData fed = new FormatEntryData();542            fed.outOfBand = true;543 544            RawTextFormatEntry rawTextEntry = new RawTextFormatEntry();545            rawTextEntry.text = so.ToString();546            fed.formatEntryInfo = rawTextEntry;547 548            return fed;549        }550    }551 552    /// <summary>553    /// Helper class to manage the logging of errors resulting from554    /// evaluations of PSPropertyExpression instances555    ///556    /// Depending on settings, it queues the failing PSPropertyExpressionResult557    /// instances and generates a list of out-of-band FormatEntryData558    /// objects to be sent to the output pipeline.559    /// </summary>560    internal sealed class FormatErrorManager561    {562        internal FormatErrorManager(FormatErrorPolicy formatErrorPolicy)563        {564            _formatErrorPolicy = formatErrorPolicy;565        }566 567        /// <summary>568        /// Log a failed evaluation of an PSPropertyExpression.569        /// </summary>570        /// <param name="result">PSPropertyExpressionResult containing the failed evaluation data.</param>571        /// <param name="sourceObject">Object used to evaluate the PSPropertyExpression.</param>572        internal void LogPSPropertyExpressionFailedResult(PSPropertyExpressionResult result, object sourceObject)573        {574            if (!_formatErrorPolicy.ShowErrorsAsMessages)575                return;576            PSPropertyExpressionError error = new PSPropertyExpressionError();577            error.result = result;578            error.sourceObject = sourceObject;579            _formattingErrorList.Add(error);580        }581 582        /// <summary>583        /// Log a failed formatting operation.584        /// </summary>585        /// <param name="error">String format error object.</param>586        internal void LogStringFormatError(StringFormatError error)587        {588            if (!_formatErrorPolicy.ShowErrorsAsMessages)589                return;590            _formattingErrorList.Add(error);591        }592 593        internal bool DisplayErrorStrings594        {595            get { return _formatErrorPolicy.ShowErrorsInFormattedOutput; }596        }597 598        internal bool DisplayFormatErrorString599        {600            get601            {602                // NOTE: we key off the same flag603                return this.DisplayErrorStrings;604            }605        }606 607        internal string ErrorString608        {609            get { return _formatErrorPolicy.errorStringInFormattedOutput; }610        }611 612        internal string FormatErrorString613        {614            get { return _formatErrorPolicy.formatErrorStringInFormattedOutput; }615        }616 617        /// <summary>618        /// Provide a list of ErrorRecord entries619        /// to be written to the error pipeline and clear the list of pending620        /// errors.621        /// </summary>622        /// <returns>List of ErrorRecord objects.</returns>623        internal List<ErrorRecord> DrainFailedResultList()624        {625            if (!_formatErrorPolicy.ShowErrorsAsMessages)626                return null;627 628            List<ErrorRecord> retVal = new List<ErrorRecord>();629            foreach (FormattingError error in _formattingErrorList)630            {631                ErrorRecord errorRecord = GenerateErrorRecord(error);632                if (errorRecord != null)633                    retVal.Add(errorRecord);634            }635 636            _formattingErrorList.Clear();637            return retVal;638        }639 640        /// <summary>641        /// Conversion between an error internal representation and ErrorRecord.642        /// </summary>643        /// <param name="error">Internal error object.</param>644        /// <returns>Corresponding ErrorRecord instance.</returns>645        private static ErrorRecord GenerateErrorRecord(FormattingError error)646        {647            ErrorRecord errorRecord = null;648            string msg = null;649            if (error is PSPropertyExpressionError psPropertyExpressionError)650            {651                errorRecord = new ErrorRecord(652                                psPropertyExpressionError.result.Exception,653                                "PSPropertyExpressionError",654                                ErrorCategory.InvalidArgument,655                                psPropertyExpressionError.sourceObject);656 657                msg = StringUtil.Format(FormatAndOut_format_xxx.PSPropertyExpressionError,658                    psPropertyExpressionError.result.ResolvedExpression.ToString());659                errorRecord.ErrorDetails = new ErrorDetails(msg);660            }661 662            if (error is StringFormatError formattingError)663            {664                errorRecord = new ErrorRecord(665                                formattingError.exception,666                                "formattingError",667                                ErrorCategory.InvalidArgument,668                                formattingError.sourceObject);669 670                msg = StringUtil.Format(FormatAndOut_format_xxx.FormattingError,671                    formattingError.formatString);672                errorRecord.ErrorDetails = new ErrorDetails(msg);673            }674 675            return errorRecord;676        }677 678        private readonly FormatErrorPolicy _formatErrorPolicy;679 680        /// <summary>681        /// Current list of failed PSPropertyExpression evaluations.682        /// </summary>683        private readonly List<FormattingError> _formattingErrorList = new List<FormattingError>();684    }685}686