MegaBites-AI/Windows-powershell
0372
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Collections.Generic;5using System.Collections.ObjectModel;6using System.IO;7using System.Reflection;8 9using System.Management.Automation.Runspaces;10 11namespace System.Management.Automation12{13 /// <summary>14 /// Class HelpProvider defines the interface to be implemented by help providers.15 ///16 /// Help Providers:17 /// The basic contract for help providers is to provide help based on the18 /// search target.19 ///20 /// The result of help provider invocation can be three things:21 /// a. Full help info. (in the case of exact-match and single search result)22 /// b. Short help info. (in the case of multiple search result)23 /// c. Partial help info. (in the case of some commandlet help info, which24 /// should be supplemented by provider help info)25 /// d. Help forwarding info. (in the case of alias, which will change the target26 /// for alias)27 ///28 /// Help providers may need to provide functionality in following two area,29 /// a. caching and indexing to boost performance30 /// b. localization31 ///32 /// Basic properties of a Help Provider33 /// 1. Name34 /// 2. Type35 /// 3. Assembly36 ///37 /// Help Provider Interface38 /// 1. Initialize:39 /// 2. ExactMatchHelp:40 /// 3. SearchHelp:41 /// 4. ProcessForwardedHelp.42 /// </summary>43 internal abstract class HelpProvider44 {45 /// <summary>46 /// Constructor for HelpProvider.47 /// </summary>48 internal HelpProvider(HelpSystem helpSystem)49 {50 _helpSystem = helpSystem;51 }52 53 private readonly HelpSystem _helpSystem;54 55 internal HelpSystem HelpSystem56 {57 get58 {59 return _helpSystem;60 }61 }62 63 #region Common Properties64 65 /// <summary>66 /// Name for the help provider.67 /// </summary>68 /// <value>Name for the help provider</value>69 /// <remarks>Derived classes should set this.</remarks>70 internal abstract string Name71 {72 get;73 }74 75 /// <summary>76 /// Help category for the help provider.77 /// </summary>78 /// <value>Help category for the help provider</value>79 /// <remarks>Derived classes should set this.</remarks>80 internal abstract HelpCategory HelpCategory81 {82 get;83 }84 85#if V286 87 /// <summary>88 /// Assembly that contains the help provider.89 /// </summary>90 /// <value>Assembly name</value>91 virtual internal string AssemblyName92 {93 get94 {95 return Assembly.GetExecutingAssembly().FullName;96 }97 }98 99 /// <summary>100 /// Class that implements the help provider.101 /// </summary>102 /// <value>Class name</value>103 virtual internal string ClassName104 {105 get106 {107 return this.GetType().FullName;108 }109 }110 111 /// <summary>112 /// Get an provider info object based on the basic information in this provider.113 /// </summary>114 /// <value>An mshObject that contains the providerInfo</value>115 internal PSObject ProviderInfo116 {117 get118 {119 PSObject result = new PSObject();120 result.Properties.Add(new PSNoteProperty("Name", this.Name));121 result.Properties.Add(new PSNoteProperty("Category", this.HelpCategory.ToString()));122 result.Properties.Add(new PSNoteProperty("ClassName", this.ClassName));123 result.Properties.Add(new PSNoteProperty("AssemblyName", this.AssemblyName));124 125 Collection<string> typeNames = new Collection<string>();126 typeNames.Add("HelpProviderInfo");127 result.TypeNames = typeNames;128 129 return result;130 }131 }132 133#endif134 135 #endregion136 137 #region Help Provider Interface138 139 /// <summary>140 /// Retrieve help info that exactly match the target.141 /// </summary>142 /// <param name="helpRequest">Help request object.</param>143 /// <returns>List of HelpInfo objects retrieved.</returns>144 internal abstract IEnumerable<HelpInfo> ExactMatchHelp(HelpRequest helpRequest);145 146 /// <summary>147 /// Search help info that match the target search pattern.148 /// </summary>149 /// <param name="helpRequest">Help request object.</param>150 /// <param name="searchOnlyContent">151 /// If true, searches for pattern in the help content. Individual152 /// provider can decide which content to search in.153 ///154 /// If false, searches for pattern in the command names.155 /// </param>156 /// <returns>A collection of help info objects.</returns>157 internal abstract IEnumerable<HelpInfo> SearchHelp(HelpRequest helpRequest, bool searchOnlyContent);158 159 /// <summary>160 /// Process a helpinfo forwarded over by another help provider.161 ///162 /// HelpProvider can choose to process the helpInfo or not,163 ///164 /// 1. If a HelpProvider chooses not to process the helpInfo, it can return null to indicate165 /// helpInfo is not processed.166 /// 2. If a HelpProvider indeed processes the helpInfo, it should create a new helpInfo167 /// object instead of modifying the passed-in helpInfo object. This is very important168 /// since the helpInfo object passed in is usually stored in cache, which can169 /// used in later queries.170 /// </summary>171 /// <param name="helpInfo">HelpInfo passed over by another HelpProvider.</param>172 /// <param name="helpRequest">Help request object.</param>173 /// <returns></returns>174 internal virtual IEnumerable<HelpInfo> ProcessForwardedHelp(HelpInfo helpInfo, HelpRequest helpRequest)175 {176 // Win8: 508648. Remove the current provides category for resolving forward help as the current177 // help provider already process it.178 helpInfo.ForwardHelpCategory ^= this.HelpCategory;179 yield return helpInfo;180 }181 182 /// <summary>183 /// Reset help provider.184 ///185 /// Normally help provider are reset after a help culture change.186 /// </summary>187 internal virtual void Reset()188 {189 return;190 }191 192 #endregion193 194 #region Utility functions195 196 /// <summary>197 /// Report help file load errors.198 ///199 /// Currently three cases are handled,200 ///201 /// 1. IOException: not able to read the file202 /// 2. SecurityException: not authorized to read the file203 /// 3. XmlException: xml schema error.204 ///205 /// This will be called either from search help or exact match help206 /// to find the error.207 /// </summary>208 /// <param name="exception"></param>209 /// <param name="target"></param>210 /// <param name="helpFile"></param>211 internal void ReportHelpFileError(Exception exception, string target, string helpFile)212 {213 ErrorRecord errorRecord = new ErrorRecord(exception, "LoadHelpFileForTargetFailed", ErrorCategory.OpenError, null);214 errorRecord.ErrorDetails = new ErrorDetails(typeof(HelpProvider).Assembly, "HelpErrors", "LoadHelpFileForTargetFailed", target, helpFile, exception.Message);215 this.HelpSystem.LastErrors.Add(errorRecord);216 return;217 }218 219 /// <summary>220 /// Each Shell ( minishell ) will have its own path specified by the221 /// application base folder, which should be the same as $pshome.222 /// </summary>223 /// <returns>String representing base directory of the executing shell.</returns>224 internal string GetDefaultShellSearchPath()225 {226 string shellID = this.HelpSystem.ExecutionContext.ShellID;227 // Beginning in PowerShell 6.0.0.12, the $pshome is no longer registry specified, we search the application base instead.228 // We use executing assemblies location in case registry entry not found229 return Utils.GetApplicationBase(shellID) ?? Path.GetDirectoryName(Environment.ProcessPath);230 }231 232 /// <summary>233 /// Gets the search paths. If the current shell is single-shell based, then the returned234 /// search path contains all the directories of currently active PSSnapIns.235 /// </summary>236 /// <returns>A collection of string representing locations.</returns>237 internal Collection<string> GetSearchPaths()238 {239 Collection<string> searchPaths = this.HelpSystem.GetSearchPaths();240 241 Diagnostics.Assert(searchPaths != null,242 "HelpSystem returned an null search path");243 244 string defaultShellSearchPath = GetDefaultShellSearchPath();245 if (!searchPaths.Contains(defaultShellSearchPath))246 {247 searchPaths.Add(defaultShellSearchPath);248 }249 250 return searchPaths;251 }252 253 #endregion254 }255}256 