Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
HelpSystem.cs927 linesDownload Raw Back to help
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.Globalization;8using System.Management.Automation.Language;9 10using Microsoft.PowerShell.Commands;11 12using System.Management.Automation.Runspaces;13using System.Management.Automation.Internal;14 15namespace System.Management.Automation16{17    /// <summary>18    /// Monad help is an architecture made up of three layers:19    ///     1. At the top is get-help commandlet from where help functionality is accessed.20    ///     2. At the middle is the help system which collects help objects based on user's request.21    ///     3. At the bottom are different help providers which provide help contents for different kinds of information requested.22    ///23    /// Class HelpSystem implements the middle layer of Monad Help.24    ///25    /// HelpSystem will provide functionalities in following areas,26    ///     1. Initialization and management of help providers27    ///     2. Help engine: this will invoke different providers based on user's request.28    ///     3. Help API: this is the API HelpSystem provide to get-help commandlet.29    ///30    /// Initialization:31    ///     Initialization of different help providers needs some context information like "ExecutionContext"32    ///33    /// Help engine:34    ///     By default, HelpInfo will be retrieved in two phases: exact-match phase and search phase.35    ///36    ///     Exact-match phase: help providers will be called in appropriate order to retrieve HelpInfo.37    ///         If a match is found, help engine will stop and return the one and only HelpInfo retrieved.38    ///39    ///     Search phase: all relevant help providers will be called to retrieve HelpInfo. (Order doesn't40    ///         matter in this case) Help engine will not stop until all help providers are called.41    ///42    ///     Behavior of the help engine can be modified based on Help API parameters in the following ways:43    ///         1. limit the number of HelpInfo to be returned.44    ///         2. specify which providers will be used.45    ///         3. general help info returned in case the search target is empty.46    ///         4. default help info (or hint) returned in case no match is found.47    ///48    /// Help API:49    ///     The Help API is the function to be called by the Get-Help cmdlet.50    ///51    ///     The following information shall be provided in Help API parameters:52    ///         1. search target: (which can be one or multiple strings)53    ///         2. help type: to limit the type of help to be searched54    ///         3. included fields: the fields to be included in the help info55    ///         4. excluded fields: the fields to be excluded in the help info56    ///         5. max number of results to be returned57    ///         6. scoring algorithm for help results58    ///         7. help reason: help can be directly invoked by end user or as a result of59    ///             some command syntax error.60    ///61    ///     [gxie, 7-25-04]: included fields, excluded fields and help reason will be handled in62    ///         get-help commandlet.63    ///64    ///     Help API's are internal. The only way to access help is by65    ///     invoking the get-help command.66    ///67    ///     To support the scenario of multiple monad engines running in one process, each68    ///     monad engine is required to have its one help system instance.69    ///70    ///     Currently each ExecutionContext has a help system instance as its member.71    ///72    /// Help Providers:73    ///     The basic contract for help providers is to provide help based on the74    ///     search target.75    ///76    ///     The result of a help provider invocation can be three things:77    ///         a. Full help info (in case of an exact-match and a single search result)78    ///         b. Short help info (in case of multiple search results)79    ///         c. Partial help info (in case of some cmdlet help info, which80    ///                                 should be supplemented by provider help info)81    ///         d. Help forwarding info (in the case of an alias, which will return the target82    ///                                   for the alias)83    ///84    ///     Help providers may need to provide functionality in the following two areas:85    ///         a. caching and indexing to boost performance86    ///         b. localization.87    /// </summary>88    internal class HelpSystem89    {90        /// <summary>91        /// Constructor for HelpSystem.92        /// </summary>93        /// <param name="context">Execution context for this help system.</param>94        internal HelpSystem(ExecutionContext context)95        {96            if (context == null)97            {98                throw PSTraceSource.NewArgumentNullException("ExecutionContext");99            }100 101            _executionContext = context;102 103            Initialize();104        }105 106        private readonly ExecutionContext _executionContext;107 108        /// <summary>109        /// ExecutionContext for the help system. Different help providers110        /// will depend on this to retrieve session-related information like111        /// session state and command discovery objects.112        /// </summary>113        /// <value></value>114        internal ExecutionContext ExecutionContext115        {116            get117            {118                return _executionContext;119            }120        }121 122        #region Progress Callback123 124        internal event EventHandler<HelpProgressEventArgs> OnProgress;125 126        #endregion127 128        #region Initialization129 130        /// <summary>131        /// Initialize the help system with an execution context. If the execution context132        /// matches the execution context of current singleton HelpSystem object, nothing133        /// needs to be done. Otherwise, a new singleton HelpSystem object will be created134        /// with the new execution context.135        /// </summary>136        internal void Initialize()137        {138            _verboseHelpErrors = LanguagePrimitives.IsTrue(139                _executionContext.GetVariableValue(SpecialVariables.VerboseHelpErrorsVarPath, false));140            _helpErrorTracer = new HelpErrorTracer(this);141 142            InitializeHelpProviders();143        }144 145        #endregion Initialization146 147        #region Help API148 149        /// <summary>150        /// Get Help API function. This is the basic form of the Help API using help151        /// request.152        ///153        /// Variants of this function are defined below, which will create help request154        /// object on the fly.155        /// </summary>156        /// <param name="helpRequest">HelpRequest object</param>157        /// <returns>An array of HelpInfo objects</returns>158        internal IEnumerable<HelpInfo> GetHelp(HelpRequest helpRequest)159        {160            if (helpRequest == null)161                return null;162 163            helpRequest.Validate();164 165            ValidateHelpCulture();166 167            return this.DoGetHelp(helpRequest);168        }169 170        #endregion Help API171 172        #region Error Handling173 174        private readonly Collection<ErrorRecord> _lastErrors = new Collection<ErrorRecord>();175 176        /// <summary>177        /// This is for tracking the last set of errors happened during the help178        /// search.179        /// </summary>180        /// <value></value>181        internal Collection<ErrorRecord> LastErrors182        {183            get184            {185                return _lastErrors;186            }187        }188 189        private HelpCategory _lastHelpCategory = HelpCategory.None;190 191        /// <summary>192        /// This is the help category to search for help for the last command.193        /// </summary>194        /// <value>help category to search for help</value>195        internal HelpCategory LastHelpCategory196        {197            get198            {199                return _lastHelpCategory;200            }201        }202 203        #endregion204 205        #region Configuration206 207        private bool _verboseHelpErrors = false;208 209        /// <summary>210        /// VerboseHelpErrors is used in the case when end users are interested211        /// to know all errors that happened during a help search. This property212        /// is false by default.213        ///214        /// If this property is turned on (by setting session variable "VerboseHelpError"),215        /// following two behaviours will be different,216        ///     a. Help errors will be written to the error pipeline regardless of the situation.217        ///        (Normally, help errors will be written to error pipeline if there is no218        ///         help found and there is no wildcard in help search target).219        ///     b. Some additional warnings, including MAML processing warnings, will be220        ///        written to the error pipeline.221        /// </summary>222        /// <value></value>223        internal bool VerboseHelpErrors224        {225            get226            {227                return _verboseHelpErrors;228            }229        }230 231        #endregion232 233        #region Help Engine234 235        // Cache of search paths that are currently active.236        // This will save a lot time when help providers do their searching237        private Collection<string> _searchPaths = null;238 239        /// <summary>240        /// Gets the search paths for external snapins/modules that are currently loaded.241        /// If the current shell is single-shell-based, then the returned242        /// search path contains all the directories of currently active PSSnapIns/modules.243        /// </summary>244        /// <returns>A collection of strings representing locations.</returns>245        internal Collection<string> GetSearchPaths()246        {247            // return the cache if already present.248            if (_searchPaths != null)249            {250                return _searchPaths;251            }252 253            _searchPaths = new Collection<string>();254 255            // add loaded modules paths to the search path256            if (ExecutionContext.Modules != null)257            {258                foreach (PSModuleInfo loadedModule in ExecutionContext.Modules.ModuleTable.Values)259                {260                    if (!_searchPaths.Contains(loadedModule.ModuleBase))261                    {262                        _searchPaths.Add(loadedModule.ModuleBase);263                    }264                }265            }266 267            return _searchPaths;268        }269 270        /// <summary>271        /// Get help based on the target, help type, etc272        ///273        /// Help engine retrieve help based on following schemes:274        ///275        ///     1. if the help target is empty, get default help276        ///     2. if the help target is not a search pattern, try to retrieve exact help277        ///     3. if help target is a search pattern or step 2 returns no helpInfo, try to search for help278        ///        (Search for pattern in command name followed by pattern match in help content)279        ///     4. if step 3 returns exactly one helpInfo object, try to retrieve exact help.280        /// </summary>281        /// <param name="helpRequest">Help request object.</param>282        /// <returns>An array of HelpInfo objects</returns>283        private IEnumerable<HelpInfo> DoGetHelp(HelpRequest helpRequest)284        {285            _lastErrors.Clear();286            // Reset SearchPaths287            _searchPaths = null;288 289            _lastHelpCategory = helpRequest.HelpCategory;290 291            if (string.IsNullOrEmpty(helpRequest.Target))292            {293                HelpInfo helpInfo = GetDefaultHelp();294 295                if (helpInfo != null)296                {297                    yield return helpInfo;298                }299 300                yield return null;301            }302            else303            {304                bool isMatchFound = false;305                if (!WildcardPattern.ContainsWildcardCharacters(helpRequest.Target))306                {307                    foreach (HelpInfo helpInfo in ExactMatchHelp(helpRequest))308                    {309                        isMatchFound = true;310                        yield return helpInfo;311                    }312                }313 314                if (!isMatchFound)315                {316                    foreach (HelpInfo helpInfo in SearchHelp(helpRequest))317                    {318                        isMatchFound = true;319                        yield return helpInfo;320                    }321 322                    if (!isMatchFound)323                    {324                        // Throwing an exception here may not be the325                        // best thing to do. Instead we can choose to326                        //    a. give a hint327                        //    b. just silently return an empty search result.328                        // Solution:329                        //    If it is an exact help target, throw an exception.330                        //    Otherwise, return empty result set.331                        if (!WildcardPattern.ContainsWildcardCharacters(helpRequest.Target) && this.LastErrors.Count == 0)332                        {333                            Exception e = new HelpNotFoundException(helpRequest.Target);334                            ErrorRecord errorRecord = new ErrorRecord(e, "HelpNotFound", ErrorCategory.ResourceUnavailable, null);335                            this.LastErrors.Add(errorRecord);336                            yield break;337                        }338                    }339                }340            }341        }342 343        /// <summary>344        /// Get help that exactly matches the target.345        ///346        /// If the helpInfo returned is not complete, we shall forward the347        /// helpInfo object to the appropriate help provider for further processing.348        /// (this is implemented by ForwardHelp)349        /// </summary>350        /// <param name="helpRequest">Help request object</param>351        /// <returns>HelpInfo object retrieved (can be null)</returns>352        internal IEnumerable<HelpInfo> ExactMatchHelp(HelpRequest helpRequest)353        {354            bool isHelpInfoFound = false;355            for (int i = 0; i < this.HelpProviders.Count; i++)356            {357                HelpProvider helpProvider = (HelpProvider)this.HelpProviders[i];358                if ((helpProvider.HelpCategory & helpRequest.HelpCategory) > 0)359                {360                    foreach (HelpInfo helpInfo in helpProvider.ExactMatchHelp(helpRequest))361                    {362                        isHelpInfoFound = true;363                        foreach (HelpInfo fwdHelpInfo in ForwardHelp(helpInfo, helpRequest))364                        {365                            yield return fwdHelpInfo;366                        }367                    }368                }369 370                // Bug Win7 737383: Win7 RTM shows both function and cmdlet help when there is371                // function and cmdlet with the same name. So, ignoring the ScriptCommandHelpProvider's372                // results and going to the CommandHelpProvider for further evaluation.373                if (isHelpInfoFound && helpProvider is not ScriptCommandHelpProvider)374                {375                    // once helpInfo found from a provider..no need to traverse other providers.376                    yield break;377                }378            }379        }380 381        /// <summary>382        /// Forward help to the help provider with type forwardHelpCategory.383        ///384        /// This is used in the following known scenarios so far385        ///     1. Alias: helpInfo returned by Alias is not what end user needed.386        ///               The real help can be retrieved from Command help provider.387        /// </summary>388        /// <param name="helpInfo"></param>389        /// <param name="helpRequest">Help request object.</param>390        /// <returns>Never returns null.</returns>391        /// <remarks>helpInfos is not null or empty.</remarks>392        private IEnumerable<HelpInfo> ForwardHelp(HelpInfo helpInfo, HelpRequest helpRequest)393        {394            // findout if this helpInfo needs to be processed further..395            if (helpInfo.ForwardHelpCategory == HelpCategory.None && string.IsNullOrEmpty(helpInfo.ForwardTarget))396            {397                // this helpInfo is final...so store this in result398                // and move on..399                yield return helpInfo;400            }401            else402            {403                // Find out a capable provider to process this request...404                HelpCategory forwardHelpCategory = helpInfo.ForwardHelpCategory;405                bool isHelpInfoProcessed = false;406                for (int i = 0; i < this.HelpProviders.Count; i++)407                {408                    HelpProvider helpProvider = (HelpProvider)this.HelpProviders[i];409                    if ((helpProvider.HelpCategory & forwardHelpCategory) != HelpCategory.None)410                    {411                        isHelpInfoProcessed = true;412                        // If this help info is processed by this provider already, break413                        // out of the provider loop...414                        foreach (HelpInfo fwdResult in helpProvider.ProcessForwardedHelp(helpInfo, helpRequest))415                        {416                            // Add each helpinfo to our repository417                            foreach (HelpInfo fHelpInfo in ForwardHelp(fwdResult, helpRequest))418                            {419                                yield return fHelpInfo;420                            }421 422                            // get out of the provider loop..423                            yield break;424                        }425                    }426                }427 428                if (!isHelpInfoProcessed)429                {430                    // we are here because no help provider processed the helpinfo..431                    // so add this to our repository..432                    yield return helpInfo;433                }434            }435        }436 437        /// <summary>438        /// Get the default help info (normally when help target is empty).439        /// </summary>440        /// <returns></returns>441        private HelpInfo GetDefaultHelp()442        {443            HelpRequest helpRequest = new HelpRequest("default", HelpCategory.DefaultHelp);444            foreach (HelpInfo helpInfo in ExactMatchHelp(helpRequest))445            {446                // return just the first helpInfo object447                return helpInfo;448            }449 450            return null;451        }452 453        /// <summary>454        /// Get help that exactly match the target.455        /// </summary>456        /// <param name="helpRequest">Help request object.</param>457        /// <returns>An IEnumerable of HelpInfo object.</returns>458        private IEnumerable<HelpInfo> SearchHelp(HelpRequest helpRequest)459        {460            int countOfHelpInfosFound = 0;461            bool searchInHelpContent = false;462            bool shouldBreak = false;463 464            HelpProgressEventArgs progress = new HelpProgressEventArgs();465 466            progress.Activity = StringUtil.Format(HelpDisplayStrings.SearchingForHelpContent, helpRequest.Target);467            progress.Completed = false;468            progress.PercentComplete = 0;469 470            try471            {472                OnProgress(this, progress);473 474                // algorithm:475                // 1. Search for pattern (helpRequest.Target) in command name476                // 2. If Step 1 fails then search for pattern in help content477                do478                {479                    // we should not continue the search loop if we are480                    // searching in the help content (as this is the last step481                    // in our search algorithm).482                    if (searchInHelpContent)483                    {484                        shouldBreak = true;485                    }486 487                    for (int i = 0; i < this.HelpProviders.Count; i++)488                    {489                        HelpProvider helpProvider = (HelpProvider)this.HelpProviders[i];490                        if ((helpProvider.HelpCategory & helpRequest.HelpCategory) > 0)491                        {492                            foreach (HelpInfo helpInfo in helpProvider.SearchHelp(helpRequest, searchInHelpContent))493                            {494                                if (_executionContext.CurrentPipelineStopping)495                                {496                                    yield break;497                                }498 499                                countOfHelpInfosFound++;500                                yield return helpInfo;501 502                                if ((countOfHelpInfosFound >= helpRequest.MaxResults) && (helpRequest.MaxResults > 0))503                                {504                                    yield break;505                                }506                            }507                        }508                    }509 510                    // no need to do help content search once we have some help topics511                    // with command name search.512                    if (countOfHelpInfosFound > 0)513                    {514                        yield break;515                    }516 517                    // appears that we did not find any help matching command names..look for518                    // pattern in help content.519                    searchInHelpContent = true;520 521                    if (this.HelpProviders.Count > 0)522                    {523                        progress.PercentComplete += (100 / this.HelpProviders.Count);524                        OnProgress(this, progress);525                    }526                } while (!shouldBreak);527            }528            finally529            {530                progress.Completed = true;531                progress.PercentComplete = 100;532 533                OnProgress(this, progress);534            }535        }536 537        #endregion Help Engine538 539        #region Help Provider Manager540 541        private readonly ArrayList _helpProviders = new ArrayList();542 543        /// <summary>544        /// Return the list of help providers initialized.545        /// </summary>546        /// <value>a list of help providers</value>547        internal ArrayList HelpProviders548        {549            get550            {551                return _helpProviders;552            }553        }554 555        /// <summary>556        /// Initialize help providers.557        /// </summary>558        /// <remarks>559        /// Currently we hardcode the sequence of help provider initialization.560        /// In the longer run, we probably will load help providers based on some provider catalog. That561        /// will allow new providers to be defined by customer.562        /// </remarks>563        private void InitializeHelpProviders()564        {565            HelpProvider helpProvider = null;566 567            helpProvider = new AliasHelpProvider(this);568            _helpProviders.Add(helpProvider);569 570            helpProvider = new ScriptCommandHelpProvider(this);571            _helpProviders.Add(helpProvider);572 573            helpProvider = new CommandHelpProvider(this);574            _helpProviders.Add(helpProvider);575 576            helpProvider = new ProviderHelpProvider(this);577            _helpProviders.Add(helpProvider);578 579            helpProvider = new PSClassHelpProvider(this);580            _helpProviders.Add(helpProvider);581 582            /* TH Bug#3141590 - Disable DscResourceHelp for ClientRTM due to perf issue.583#if !CORECLR // TODO:CORECLR Add this back in once we support Get-DscResource584            helpProvider = new DscResourceHelpProvider(this);585            _helpProviders.Add(helpProvider);586#endif587            */588            helpProvider = new HelpFileHelpProvider(this);589            _helpProviders.Add(helpProvider);590 591            helpProvider = new DefaultHelpProvider(this);592            _helpProviders.Add(helpProvider);593        }594 595#if _HelpProviderReflection596 597        // Eventually we will publicize the provider api and initialize598        // help providers using reflection. This is not in v1 right now.599        //600        private static HelpProviderInfo[] _providerInfos = new HelpProviderInfo[]601                            { new HelpProviderInfo(string.Empty, "AliasHelpProvider", HelpCategory.Alias),602                              new HelpProviderInfo(string.Empty, "CommandHelpProvider", HelpCategory.Command),603                              new HelpProviderInfo(string.Empty, "ProviderHelpProvider", HelpCategory.Provider),604                              new HelpProviderInfo(string.Empty, "OverviewHelpProvider", HelpCategory.Overview),605                              new HelpProviderInfo(string.Empty, "GeneralHelpProvider", HelpCategory.General),606                              new HelpProviderInfo(string.Empty, "FAQHelpProvider", HelpCategory.FAQ),607                              new HelpProviderInfo(string.Empty, "GlossaryHelpProvider", HelpCategory.Glossary),608                              new HelpProviderInfo(string.Empty, "HelpFileHelpProvider", HelpCategory.HelpFile),609                              new HelpProviderInfo(string.Empty, "DefaultHelpHelpProvider", HelpCategory.DefaultHelp)610                            };611 612        private void InitializeHelpProviders()613        {614            for (int i = 0; i < _providerInfos.Length; i++)615            {616                HelpProvider helpProvider = GetHelpProvider(_providerInfos[i]);617 618                if (helpProvider != null)619                {620                    helpProvider.Initialize(this._executionContext);621                    _helpProviders.Add(helpProvider);622                }623            }624        }625 626        private HelpProvider GetHelpProvider(HelpProviderInfo providerInfo)627        {628            Assembly providerAssembly = null;629 630            if (string.IsNullOrEmpty(providerInfo.AssemblyName))631            {632                providerAssembly = Assembly.GetExecutingAssembly();633            }634            else635            {636                providerAssembly = Assembly.Load(providerInfo.AssemblyName);637            }638 639            try640            {641                if (providerAssembly != null)642                {643                    HelpProvider helpProvider =644                        (HelpProvider)providerAssembly.CreateInstance(providerInfo.ClassName,645                                                                     false, // don't ignore case646                                                                     BindingFlags.CreateInstance,647                                                                     null, // use default binder648                                                                     null,649                                                                     null, // use current culture650                                                                     null // no special activation attributes651                                                                    );652 653                    return helpProvider;654                }655            }656            catch (TargetInvocationException e)657            {658                System.Console.WriteLine(e.Message);659                if (e.InnerException != null)660                {661                    System.Console.WriteLine(e.InnerException.Message);662                    System.Console.WriteLine(e.InnerException.StackTrace);663                }664            }665 666            return null;667        }668 669#endif670 671        #endregion Help Provider Manager672 673        #region Help Error Tracer674 675        private HelpErrorTracer _helpErrorTracer;676 677        /// <summary>678        /// The error tracer for this help system.679        /// </summary>680        /// <value></value>681        internal HelpErrorTracer HelpErrorTracer682        {683            get684            {685                return _helpErrorTracer;686            }687        }688 689        /// <summary>690        /// Start a trace frame for a help file.691        /// </summary>692        /// <param name="helpFile"></param>693        /// <returns></returns>694        internal IDisposable Trace(string helpFile)695        {696            if (_helpErrorTracer == null)697                return null;698 699            return _helpErrorTracer.Trace(helpFile);700        }701 702        /// <summary>703        /// Trace an error within a help frame, which is tracked by help tracer itself.704        /// </summary>705        /// <param name="errorRecord"></param>706        internal void TraceError(ErrorRecord errorRecord)707        {708            if (_helpErrorTracer == null)709                return;710 711            _helpErrorTracer.TraceError(errorRecord);712        }713 714        /// <summary>715        /// Trace a collection of errors within a help frame, which is tracked by716        /// help tracer itself.717        /// </summary>718        /// <param name="errorRecords"></param>719        internal void TraceErrors(Collection<ErrorRecord> errorRecords)720        {721            if (_helpErrorTracer == null || errorRecords == null)722                return;723 724            _helpErrorTracer.TraceErrors(errorRecords);725        }726 727        #endregion728 729        #region Help MUI730 731        private CultureInfo _culture;732 733        /// <summary>734        /// Before each help request is serviced, current thread culture will validate735        /// against the current culture of help system. If there is a miss match, each736        /// help provider will be notified of the culture change.737        /// </summary>738        private void ValidateHelpCulture()739        {740            CultureInfo culture = CultureInfo.CurrentUICulture;741 742            if (_culture == null)743            {744                _culture = culture;745                return;746            }747 748            if (_culture.Equals(culture))749            {750                return;751            }752 753            _culture = culture;754            ResetHelpProviders();755        }756 757        /// <summary>758        /// Reset help providers providers. This normally corresponds to help culture change.759        ///760        /// Normally help providers will remove cached help content to make sure new help761        /// requests will be served with content of right culture.762        /// </summary>763        internal void ResetHelpProviders()764        {765            if (_helpProviders == null)766                return;767 768            for (int i = 0; i < _helpProviders.Count; i++)769            {770                HelpProvider helpProvider = (HelpProvider)_helpProviders[i];771 772                helpProvider.Reset();773            }774 775            return;776        }777 778        #endregion779 780        #region ScriptBlock Parse Tokens Caching/Clearing Functionality781 782        private readonly Lazy<Dictionary<Ast, Token[]>> _scriptBlockTokenCache = new Lazy<Dictionary<Ast, Token[]>>(isThreadSafe: true);783 784        internal Dictionary<Ast, Token[]> ScriptBlockTokenCache785        {786            get { return _scriptBlockTokenCache.Value; }787        }788 789        internal void ClearScriptBlockTokenCache()790        {791            if (_scriptBlockTokenCache.IsValueCreated)792            {793                _scriptBlockTokenCache.Value.Clear();794            }795        }796 797        #endregion798    }799 800    /// <summary>801    /// Help progress info.802    /// </summary>803    internal class HelpProgressEventArgs : EventArgs804    {805        internal bool Completed { get; set; }806 807        internal string Activity { get; set; }808 809        internal int PercentComplete { get; set; }810    }811 812    /// <summary>813    /// This is the structure to keep track of HelpProvider Info.814    /// </summary>815    internal class HelpProviderInfo816    {817        internal string AssemblyName = string.Empty;818        internal string ClassName = string.Empty;819        internal HelpCategory HelpCategory = HelpCategory.None;820 821        /// <summary>822        /// Constructor.823        /// </summary>824        /// <param name="assemblyName">Assembly that contains this help provider.</param>825        /// <param name="className">The class that implements this help provider.</param>826        /// <param name="helpCategory">Help category of this help provider.</param>827        internal HelpProviderInfo(string assemblyName, string className, HelpCategory helpCategory)828        {829            this.AssemblyName = assemblyName;830            this.ClassName = className;831            this.HelpCategory = helpCategory;832        }833    }834 835    /// <summary>836    /// Help categories.837    /// </summary>838    [Flags]839    internal enum HelpCategory840    {841        /// <summary>842        /// Undefined help category.843        /// </summary>844        None = 0x00,845 846        /// <summary>847        /// Alias help.848        /// </summary>849        Alias = 0x01,850 851        /// <summary>852        /// Cmdlet help.853        /// </summary>854        Cmdlet = 0x02,855 856        /// <summary>857        /// Provider help.858        /// </summary>859        Provider = 0x04,860 861        /// <summary>862        /// General keyword help.863        /// </summary>864        General = 0x10,865 866        /// <summary>867        /// FAQ's.868        /// </summary>869        FAQ = 0x20,870 871        /// <summary>872        /// Glossary and term definitions.873        /// </summary>874        Glossary = 0x40,875 876        /// <summary>877        /// Help that is contained in help file.878        /// </summary>879        HelpFile = 0x80,880 881        /// <summary>882        /// Help from a script block.883        /// </summary>884        ScriptCommand = 0x100,885 886        /// <summary>887        /// Help for a function.888        /// </summary>889        Function = 0x200,890 891        /// <summary>892        /// Help for a filter.893        /// </summary>894        Filter = 0x400,895 896        /// <summary>897        /// Help for an external script (i.e. for a *.ps1 file)898        /// </summary>899        ExternalScript = 0x800,900 901        /// <summary>902        /// All help categories.903        /// </summary>904        All = 0xFFFFF,905 906        /// <summary>907        /// Default Help.908        /// </summary>909        DefaultHelp = 0x1000,910 911        /// <summary>912        /// Help for a Configuration.913        /// </summary>914        Configuration = 0x4000,915 916        /// <summary>917        /// Help for DSC Resource.918        /// </summary>919        DscResource = 0x8000,920 921        /// <summary>922        /// Help for PS Classes.923        /// </summary>924        Class = 0x10000925    }926}927