MegaBites-AI/Windows-powershell
0372
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.Runspaces;11using System.Reflection;12using System.Text;13 14namespace System.Management.Automation.Help15{16 /// <summary>17 /// Positional parameter comparer.18 /// </summary>19 internal class PositionalParameterComparer : IComparer20 {21 /// <summary>22 /// </summary>23 /// <param name="x"></param>24 /// <param name="y"></param>25 /// <returns></returns>26 public int Compare(object x, object y)27 {28 CommandParameterInfo a = x as CommandParameterInfo;29 CommandParameterInfo b = y as CommandParameterInfo;30 31 Debug.Assert(a != null && b != null);32 33 return (a.Position - b.Position);34 }35 }36 37 /// <summary>38 /// The help object builder class attempts to create a full HelpInfo object from39 /// a CmdletInfo object. This is used to generate the default UX when no help content40 /// is present in the box. This class mimics the exact same structure as that of a MAML41 /// node, so that the default UX does not introduce regressions.42 /// </summary>43 internal static class DefaultCommandHelpObjectBuilder44 {45 internal static readonly string TypeNameForDefaultHelp = "ExtendedCmdletHelpInfo";46 /// <summary>47 /// Generates a HelpInfo PSObject from a CmdletInfo object.48 /// </summary>49 /// <param name="input">Command info.</param>50 /// <returns>HelpInfo PSObject.</returns>51 internal static PSObject GetPSObjectFromCmdletInfo(CommandInfo input)52 {53 // Create a copy of commandInfo for GetCommandCommand so that we can generate parameter54 // sets based on Dynamic Parameters (+ optional arguments)55 CommandInfo commandInfo = input.CreateGetCommandCopy(null);56 57 PSObject obj = new PSObject();58 59 obj.TypeNames.Clear();60 obj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#{commandInfo.ModuleName}#command"));61 obj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#{commandInfo.ModuleName}"));62 obj.TypeNames.Add(DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp);63 obj.TypeNames.Add("CmdletHelpInfo");64 obj.TypeNames.Add("HelpInfo");65 66 if (commandInfo is CmdletInfo cmdletInfo)67 {68 bool common = false;69 if (cmdletInfo.Parameters != null)70 {71 common = HasCommonParameters(cmdletInfo.Parameters);72 }73 74 obj.Properties.Add(new PSNoteProperty("CommonParameters", common));75 AddDetailsProperties(obj, cmdletInfo.Name, cmdletInfo.Noun, cmdletInfo.Verb, TypeNameForDefaultHelp);76 AddSyntaxProperties(obj, cmdletInfo.Name, cmdletInfo.ParameterSets, common, TypeNameForDefaultHelp);77 AddParametersProperties(obj, cmdletInfo.Parameters, common, TypeNameForDefaultHelp);78 AddInputTypesProperties(obj, cmdletInfo.Parameters);79 AddRelatedLinksProperties(obj, commandInfo.CommandMetadata.HelpUri);80 81 try82 {83 AddOutputTypesProperties(obj, cmdletInfo.OutputType);84 }85 catch (PSInvalidOperationException)86 {87 AddOutputTypesProperties(obj, new ReadOnlyCollection<PSTypeName>(new List<PSTypeName>()));88 }89 90 AddAliasesProperties(obj, cmdletInfo.Name, cmdletInfo.Context);91 92 if (HasHelpInfoUri(cmdletInfo.Module, cmdletInfo.ModuleName))93 {94 AddRemarksProperties(obj, cmdletInfo.Name, cmdletInfo.CommandMetadata.HelpUri);95 }96 else97 {98 obj.Properties.Add(new PSNoteProperty("remarks", HelpDisplayStrings.None));99 }100 101 obj.Properties.Add(new PSNoteProperty("PSSnapIn", cmdletInfo.PSSnapIn));102 }103 else if (commandInfo is FunctionInfo funcInfo)104 {105 bool common = HasCommonParameters(funcInfo.Parameters);106 107 obj.Properties.Add(new PSNoteProperty("CommonParameters", common));108 AddDetailsProperties(obj, funcInfo.Name, string.Empty, string.Empty, TypeNameForDefaultHelp);109 AddSyntaxProperties(obj, funcInfo.Name, funcInfo.ParameterSets, common, TypeNameForDefaultHelp);110 AddParametersProperties(obj, funcInfo.Parameters, common, TypeNameForDefaultHelp);111 AddInputTypesProperties(obj, funcInfo.Parameters);112 AddRelatedLinksProperties(obj, funcInfo.CommandMetadata.HelpUri);113 114 try115 {116 AddOutputTypesProperties(obj, funcInfo.OutputType);117 }118 catch (PSInvalidOperationException)119 {120 AddOutputTypesProperties(obj, new ReadOnlyCollection<PSTypeName>(new List<PSTypeName>()));121 }122 123 AddAliasesProperties(obj, funcInfo.Name, funcInfo.Context);124 125 if (HasHelpInfoUri(funcInfo.Module, funcInfo.ModuleName))126 {127 AddRemarksProperties(obj, funcInfo.Name, funcInfo.CommandMetadata.HelpUri);128 }129 else130 {131 obj.Properties.Add(new PSNoteProperty("remarks", HelpDisplayStrings.None));132 }133 }134 135 obj.Properties.Add(new PSNoteProperty("alertSet", null));136 obj.Properties.Add(new PSNoteProperty("description", null));137 obj.Properties.Add(new PSNoteProperty("examples", null));138 obj.Properties.Add(new PSNoteProperty("Synopsis", commandInfo.Syntax));139 obj.Properties.Add(new PSNoteProperty("ModuleName", commandInfo.ModuleName));140 obj.Properties.Add(new PSNoteProperty("nonTerminatingErrors", string.Empty));141 obj.Properties.Add(new PSNoteProperty("xmlns:command", "http://schemas.microsoft.com/maml/dev/command/2004/10"));142 obj.Properties.Add(new PSNoteProperty("xmlns:dev", "http://schemas.microsoft.com/maml/dev/2004/10"));143 obj.Properties.Add(new PSNoteProperty("xmlns:maml", "http://schemas.microsoft.com/maml/2004/10"));144 145 return obj;146 }147 148 /// <summary>149 /// Adds the details properties.150 /// </summary>151 /// <param name="obj">HelpInfo object.</param>152 /// <param name="name">Command name.</param>153 /// <param name="noun">Command noun.</param>154 /// <param name="verb">Command verb.</param>155 /// <param name="typeNameForHelp">Type name for help.</param>156 /// <param name="synopsis">Synopsis.</param>157 internal static void AddDetailsProperties(PSObject obj, string name, string noun, string verb, string typeNameForHelp,158 string synopsis = null)159 {160 PSObject mshObject = new PSObject();161 162 mshObject.TypeNames.Clear();163 mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#details"));164 165 mshObject.Properties.Add(new PSNoteProperty("name", name));166 mshObject.Properties.Add(new PSNoteProperty("noun", noun));167 mshObject.Properties.Add(new PSNoteProperty("verb", verb));168 169 // add synopsis170 if (!string.IsNullOrEmpty(synopsis))171 {172 PSObject descriptionObject = new PSObject();173 descriptionObject.TypeNames.Clear();174 descriptionObject.TypeNames.Add("MamlParaTextItem");175 descriptionObject.Properties.Add(new PSNoteProperty("Text", synopsis));176 mshObject.Properties.Add(new PSNoteProperty("Description", descriptionObject));177 }178 179 obj.Properties.Add(new PSNoteProperty("details", mshObject));180 }181 182 /// <summary>183 /// Adds the syntax properties.184 /// </summary>185 /// <param name="obj">HelpInfo object.</param>186 /// <param name="cmdletName">Command name.</param>187 /// <param name="parameterSets">Parameter sets.</param>188 /// <param name="common">Common parameters.</param>189 /// <param name="typeNameForHelp">Type name for help.</param>190 internal static void AddSyntaxProperties(PSObject obj, string cmdletName, ReadOnlyCollection<CommandParameterSetInfo> parameterSets, bool common, string typeNameForHelp)191 {192 PSObject mshObject = new PSObject();193 194 mshObject.TypeNames.Clear();195 mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#syntax"));196 197 AddSyntaxItemProperties(mshObject, cmdletName, parameterSets, common, typeNameForHelp);198 199 obj.Properties.Add(new PSNoteProperty("Syntax", mshObject));200 }201 202 /// <summary>203 /// Add the syntax item properties.204 /// </summary>205 /// <param name="obj">HelpInfo object.</param>206 /// <param name="cmdletName">Cmdlet name, you can't get this from parameterSets.</param>207 /// <param name="parameterSets">A collection of parameter sets.</param>208 /// <param name="common">Common parameters.</param>209 /// <param name="typeNameForHelp">Type name for help.</param>210 private static void AddSyntaxItemProperties(PSObject obj, string cmdletName, ReadOnlyCollection<CommandParameterSetInfo> parameterSets, bool common, string typeNameForHelp)211 {212 ArrayList mshObjects = new ArrayList();213 214 foreach (CommandParameterSetInfo parameterSet in parameterSets)215 {216 PSObject mshObject = new PSObject();217 218 mshObject.TypeNames.Clear();219 mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#syntaxItem"));220 221 mshObject.Properties.Add(new PSNoteProperty("name", cmdletName));222 mshObject.Properties.Add(new PSNoteProperty("CommonParameters", common));223 224 Collection<CommandParameterInfo> parameters = new Collection<CommandParameterInfo>();225 // GenerateParameters parameters in display order226 // ie., Positional followed by227 // Named Mandatory (in alpha numeric) followed by228 // Named (in alpha numeric)229 parameterSet.GenerateParametersInDisplayOrder(parameters.Add, delegate { });230 231 AddSyntaxParametersProperties(mshObject, parameters, common, parameterSet.Name);232 233 mshObjects.Add(mshObject);234 }235 236 obj.Properties.Add(new PSNoteProperty("syntaxItem", mshObjects.ToArray()));237 }238 239 /// <summary>240 /// Add the syntax parameters properties (these parameters are used to create the syntax section)241 /// </summary>242 /// <param name="obj">HelpInfo object.</param>243 /// <param name="parameters">244 /// a collection of parameters in display order245 /// ie., Positional followed by246 /// Named Mandatory (in alpha numeric) followed by247 /// Named (in alpha numeric)248 /// </param>249 /// <param name="common">Common parameters.</param>250 /// <param name="parameterSetName">Name of the parameter set for which the syntax is generated.</param>251 private static void AddSyntaxParametersProperties(PSObject obj, IEnumerable<CommandParameterInfo> parameters,252 bool common, string parameterSetName)253 {254 ArrayList mshObjects = new ArrayList();255 256 foreach (CommandParameterInfo parameter in parameters)257 {258 if (common && Cmdlet.CommonParameters.Contains(parameter.Name))259 {260 continue;261 }262 263 PSObject mshObject = new PSObject();264 265 mshObject.TypeNames.Clear();266 mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#parameter"));267 268 Collection<Attribute> attributes = new Collection<Attribute>(parameter.Attributes);269 270 AddParameterProperties(mshObject, parameter.Name, new Collection<string>(parameter.Aliases),271 parameter.IsDynamic, parameter.ParameterType, attributes, parameterSetName);272 273 Collection<ValidateSetAttribute> validateSet = GetValidateSetAttribute(attributes);274 List<string> names = new List<string>();275 276 foreach (ValidateSetAttribute set in validateSet)277 {278 foreach (string value in set.ValidValues)279 {280 names.Add(value);281 }282 }283 284 if (names.Count != 0)285 {286 AddParameterValueGroupProperties(mshObject, names.ToArray());287 }288 else289 {290 if (parameter.ParameterType.IsEnum && (Enum.GetNames(parameter.ParameterType) != null))291 {292 AddParameterValueGroupProperties(mshObject, Enum.GetNames(parameter.ParameterType));293 }294 else if (parameter.ParameterType.IsArray)295 {296 if (parameter.ParameterType.GetElementType().IsEnum &&297 Enum.GetNames(parameter.ParameterType.GetElementType()) != null)298 {299 AddParameterValueGroupProperties(mshObject, Enum.GetNames(parameter.ParameterType.GetElementType()));300 }301 }302 else if (parameter.ParameterType.IsGenericType)303 {304 Type[] types = parameter.ParameterType.GetGenericArguments();305 306 if (types.Length != 0)307 {308 Type type = types[0];309 310 if (type.IsEnum && (Enum.GetNames(type) != null))311 {312 AddParameterValueGroupProperties(mshObject, Enum.GetNames(type));313 }314 else if (type.IsArray)315 {316 if (type.GetElementType().IsEnum &&317 Enum.GetNames(type.GetElementType()) != null)318 {319 AddParameterValueGroupProperties(mshObject, Enum.GetNames(type.GetElementType()));320 }321 }322 }323 }324 }325 326 mshObjects.Add(mshObject);327 }328 329 obj.Properties.Add(new PSNoteProperty("parameter", mshObjects.ToArray()));330 }331 332 /// <summary>333 /// Adds a parameter value group (for enums)334 /// </summary>335 /// <param name="obj">Object.</param>336 /// <param name="values">Parameter group values.</param>337 private static void AddParameterValueGroupProperties(PSObject obj, string[] values)338 {339 PSObject paramValueGroup = new PSObject();340 341 paramValueGroup.TypeNames.Clear();342 paramValueGroup.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#parameterValueGroup"));343 344 ArrayList paramValue = new ArrayList(values);345 346 paramValueGroup.Properties.Add(new PSNoteProperty("parameterValue", paramValue.ToArray()));347 obj.Properties.Add(new PSNoteProperty("parameterValueGroup", paramValueGroup));348 }349 350 /// <summary>351 /// Add the parameters properties (these parameters are used to create the parameters section)352 /// </summary>353 /// <param name="obj">HelpInfo object.</param>354 /// <param name="parameters">Parameters.</param>355 /// <param name="common">Common parameters.</param>356 /// <param name="typeNameForHelp">Type name for help.</param>357 internal static void AddParametersProperties(PSObject obj, Dictionary<string, ParameterMetadata> parameters, bool common, string typeNameForHelp)358 {359 PSObject paramsObject = new PSObject();360 361 paramsObject.TypeNames.Clear();362 paramsObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{typeNameForHelp}#parameters"));363 364 ArrayList paramObjects = new ArrayList();365 366 ArrayList sortedParameters = new ArrayList();367 368 if (parameters != null)369 {370 foreach (KeyValuePair<string, ParameterMetadata> parameter in parameters)371 {372 sortedParameters.Add(parameter.Key);373 }374 }375 376 sortedParameters.Sort(StringComparer.Ordinal);377 378 foreach (string parameter in sortedParameters)379 {380 if (common && Cmdlet.CommonParameters.Contains(parameter))381 {382 continue;383 }384 385 PSObject paramObject = new PSObject();386 387 paramObject.TypeNames.Clear();388 paramObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#parameter"));389 390 AddParameterProperties(paramObject, parameter, parameters[parameter].Aliases,391 parameters[parameter].IsDynamic, parameters[parameter].ParameterType, parameters[parameter].Attributes);392 393 paramObjects.Add(paramObject);394 }395 396 paramsObject.Properties.Add(new PSNoteProperty("parameter", paramObjects.ToArray()));397 obj.Properties.Add(new PSNoteProperty("parameters", paramsObject));398 }399 400 /// <summary>401 /// Adds the parameter properties.402 /// </summary>403 /// <param name="obj">HelpInfo object.</param>404 /// <param name="name">Parameter name.</param>405 /// <param name="aliases">Parameter aliases.</param>406 /// <param name="dynamic">Is dynamic parameter?</param>407 /// <param name="type">Parameter type.</param>408 /// <param name="attributes">Parameter attributes.</param>409 /// <param name="parameterSetName">Name of the parameter set for which the syntax is generated.</param>410 private static void AddParameterProperties(PSObject obj, string name, Collection<string> aliases, bool dynamic,411 Type type, Collection<Attribute> attributes, string parameterSetName = null)412 {413 Collection<ParameterAttribute> attribs = GetParameterAttribute(attributes);414 415 obj.Properties.Add(new PSNoteProperty("name", name));416 417 if (attribs.Count == 0)418 {419 obj.Properties.Add(new PSNoteProperty("required", string.Empty));420 obj.Properties.Add(new PSNoteProperty("pipelineInput", string.Empty));421 obj.Properties.Add(new PSNoteProperty("isDynamic", string.Empty));422 obj.Properties.Add(new PSNoteProperty("parameterSetName", string.Empty));423 obj.Properties.Add(new PSNoteProperty("description", string.Empty));424 obj.Properties.Add(new PSNoteProperty("position", string.Empty));425 obj.Properties.Add(new PSNoteProperty("aliases", string.Empty));426 obj.Properties.Add(new PSNoteProperty("globbing", string.Empty));427 }428 else429 {430 ParameterAttribute paramAttribute = attribs[0];431 if (!string.IsNullOrEmpty(parameterSetName))432 {433 foreach (var attrib in attribs)434 {435 if (string.Equals(attrib.ParameterSetName, parameterSetName, StringComparison.OrdinalIgnoreCase))436 {437 paramAttribute = attrib;438 break;439 }440 }441 }442 443 obj.Properties.Add(new PSNoteProperty("required", CultureInfo.CurrentCulture.TextInfo.ToLower(paramAttribute.Mandatory.ToString())));444 obj.Properties.Add(new PSNoteProperty("pipelineInput", GetPipelineInputString(paramAttribute)));445 obj.Properties.Add(new PSNoteProperty("isDynamic", CultureInfo.CurrentCulture.TextInfo.ToLower(dynamic.ToString())));446 AddParameterGlobbingProperties(obj, attributes);447 448 if (paramAttribute.ParameterSetName.Equals(ParameterAttribute.AllParameterSets, StringComparison.OrdinalIgnoreCase))449 {450 obj.Properties.Add(new PSNoteProperty("parameterSetName", StringUtil.Format(HelpDisplayStrings.AllParameterSetsName)));451 }452 else453 {454 StringBuilder sb = new StringBuilder();455 456 for (int i = 0; i < attribs.Count; i++)457 {458 sb.Append(attribs[i].ParameterSetName);459 460 if (i != (attribs.Count - 1))461 {462 sb.Append(", ");463 }464 }465 466 obj.Properties.Add(new PSNoteProperty("parameterSetName", sb.ToString()));467 }468 469 if (paramAttribute.HelpMessage != null)470 {471 StringBuilder sb = new StringBuilder();472 473 sb.AppendLine(paramAttribute.HelpMessage);474 475 obj.Properties.Add(new PSNoteProperty("description", sb.ToString()));476 }477 478 // We do not show switch parameters in the syntax section479 // (i.e. [-Syntax] not [-Syntax <SwitchParameter>]480 if (type != typeof(SwitchParameter))481 {482 AddParameterValueProperties(obj, type, attributes);483 }484 485 AddParameterTypeProperties(obj, type, attributes);486 487 if (paramAttribute.Position == int.MinValue)488 {489 obj.Properties.Add(new PSNoteProperty("position",490 StringUtil.Format(HelpDisplayStrings.NamedParameter)));491 }492 else493 {494 obj.Properties.Add(new PSNoteProperty("position",495 paramAttribute.Position.ToString(CultureInfo.InvariantCulture)));496 }497 498 if (aliases.Count == 0)499 {500 obj.Properties.Add(new PSNoteProperty("aliases", StringUtil.Format(501 HelpDisplayStrings.None)));502 }503 else504 {505 StringBuilder sb = new StringBuilder();506 507 for (int i = 0; i < aliases.Count; i++)508 {509 sb.Append(aliases[i]);510 511 if (i != (aliases.Count - 1))512 {513 sb.Append(", ");514 }515 }516 517 obj.Properties.Add(new PSNoteProperty("aliases", sb.ToString()));518 }519 }520 }521 522 /// <summary>523 /// Adds the globbing properties.524 /// </summary>525 /// <param name="obj">HelpInfo object.</param>526 /// <param name="attributes">The attributes of the parameter (needed to look for PSTypeName).</param>527 private static void AddParameterGlobbingProperties(PSObject obj, IEnumerable<Attribute> attributes)528 {529 bool globbing = false;530 531 foreach (var attrib in attributes)532 {533 if (attrib is SupportsWildcardsAttribute)534 {535 globbing = true;536 break;537 }538 }539 540 obj.Properties.Add(new PSNoteProperty("globbing", CultureInfo.CurrentCulture.TextInfo.ToLower(globbing.ToString())));541 }542 543 /// <summary>544 /// Adds the parameterType properties.545 /// </summary>546 /// <param name="obj">HelpInfo object.</param>547 /// <param name="parameterType">The type of a parameter.</param>548 /// <param name="attributes">The attributes of the parameter (needed to look for PSTypeName).</param>549 private static void AddParameterTypeProperties(PSObject obj, Type parameterType, IEnumerable<Attribute> attributes)550 {551 PSObject mshObject = new PSObject();552 553 mshObject.TypeNames.Clear();554 mshObject.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#type"));555 556 var parameterTypeString = CommandParameterSetInfo.GetParameterTypeString(parameterType, attributes);557 mshObject.Properties.Add(new PSNoteProperty("name", parameterTypeString));558 559 obj.Properties.Add(new PSNoteProperty("type", mshObject));560 }561 562 /// <summary>563 /// Adds the parameterValue properties.564 /// </summary>565 /// <param name="obj">HelpInfo object.</param>566 /// <param name="parameterType">The type of a parameter.</param>567 /// <param name="attributes">The attributes of the parameter (needed to look for PSTypeName).</param>568 private static void AddParameterValueProperties(PSObject obj, Type parameterType, IEnumerable<Attribute> attributes)569 {570 PSObject mshObject;571 572 if (parameterType != null)573 {574 Type type = Nullable.GetUnderlyingType(parameterType) ?? parameterType;575 var parameterTypeString = CommandParameterSetInfo.GetParameterTypeString(parameterType, attributes);576 mshObject = new PSObject(parameterTypeString);577 mshObject.Properties.Add(new PSNoteProperty("variableLength", parameterType.IsArray));578 }579 else580 {581 mshObject = new PSObject("System.Object");582 mshObject.Properties.Add(new PSNoteProperty("variableLength",583 StringUtil.Format(HelpDisplayStrings.FalseShort)));584 }585 586 mshObject.Properties.Add(new PSNoteProperty("required", "true"));587 588 obj.Properties.Add(new PSNoteProperty("parameterValue", mshObject));589 }590 591 /// <summary>592 /// Adds the InputTypes properties.593 /// </summary>594 /// <param name="obj">HelpInfo object.</param>595 /// <param name="parameters">Command parameters.</param>596 internal static void AddInputTypesProperties(PSObject obj, Dictionary<string, ParameterMetadata> parameters)597 {598 Collection<string> inputs = new Collection<string>();599 600 if (parameters != null)601 {602 foreach (KeyValuePair<string, ParameterMetadata> parameter in parameters)603 {604 Collection<ParameterAttribute> attribs = GetParameterAttribute(parameter.Value.Attributes);605 606 foreach (ParameterAttribute attrib in attribs)607 {608 if (attrib.ValueFromPipeline || attrib.ValueFromPipelineByPropertyName)609 {610 if (!inputs.Contains(parameter.Value.ParameterType.FullName))611 {612 inputs.Add(parameter.Value.ParameterType.FullName);613 }614 }615 }616 }617 }618 619 if (inputs.Count == 0)620 {621 inputs.Add(StringUtil.Format(HelpDisplayStrings.None));622 }623 624 StringBuilder sb = new StringBuilder();625 626 foreach (string input in inputs)627 {628 sb.AppendLine(input);629 }630 631 PSObject inputTypesObj = new PSObject();632 633 inputTypesObj.TypeNames.Clear();634 inputTypesObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#inputTypes"));635 636 PSObject inputTypeObj = new PSObject();637 638 inputTypeObj.TypeNames.Clear();639 inputTypeObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#inputType"));640 641 PSObject typeObj = new PSObject();642 643 typeObj.TypeNames.Clear();644 typeObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#type"));645 646 typeObj.Properties.Add(new PSNoteProperty("name", sb.ToString()));647 inputTypeObj.Properties.Add(new PSNoteProperty("type", typeObj));648 inputTypesObj.Properties.Add(new PSNoteProperty("inputType", inputTypeObj));649 obj.Properties.Add(new PSNoteProperty("inputTypes", inputTypesObj));650 }651 652 /// <summary>653 /// Adds the OutputTypes properties.654 /// </summary>655 /// <param name="obj">HelpInfo object.</param>656 /// <param name="outputTypes">Output types.</param>657 private static void AddOutputTypesProperties(PSObject obj, ReadOnlyCollection<PSTypeName> outputTypes)658 {659 PSObject returnValuesObj = new PSObject();660 661 returnValuesObj.TypeNames.Clear();662 returnValuesObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#returnValues"));663 664 PSObject returnValueObj = new PSObject();665 666 returnValueObj.TypeNames.Clear();667 returnValueObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#returnValue"));668 669 PSObject typeObj = new PSObject();670 671 typeObj.TypeNames.Clear();672 typeObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#type"));673 674 if (outputTypes.Count == 0)675 {676 typeObj.Properties.Add(new PSNoteProperty("name", "System.Object"));677 }678 else679 {680 StringBuilder sb = new StringBuilder();681 682 foreach (PSTypeName outputType in outputTypes)683 {684 sb.AppendLine(outputType.Name);685 }686 687 typeObj.Properties.Add(new PSNoteProperty("name", sb.ToString()));688 }689 690 returnValueObj.Properties.Add(new PSNoteProperty("type", typeObj));691 returnValuesObj.Properties.Add(new PSNoteProperty("returnValue", returnValueObj));692 obj.Properties.Add(new PSNoteProperty("returnValues", returnValuesObj));693 }694 695 /// <summary>696 /// Adds the aliases properties.697 /// </summary>698 /// <param name="obj">HelpInfo object.</param>699 /// <param name="name">Command name.</param>700 /// <param name="context">Execution context.</param>701 private static void AddAliasesProperties(PSObject obj, string name, ExecutionContext context)702 {703 StringBuilder sb = new StringBuilder();704 705 bool found = false;706 707 if (context != null)708 {709 foreach (string alias in context.SessionState.Internal.GetAliasesByCommandName(name))710 {711 found = true;712 sb.AppendLine(alias);713 }714 }715 716 if (!found)717 {718 sb.AppendLine(StringUtil.Format(HelpDisplayStrings.None));719 }720 721 obj.Properties.Add(new PSNoteProperty("aliases", sb.ToString()));722 }723 724 /// <summary>725 /// Adds the remarks properties.726 /// </summary>727 /// <param name="obj">HelpInfo object.</param>728 /// <param name="cmdletName"></param>729 /// <param name="helpUri"></param>730 private static void AddRemarksProperties(PSObject obj, string cmdletName, string helpUri)731 {732 if (string.IsNullOrEmpty(helpUri))733 {734 obj.Properties.Add(new PSNoteProperty("remarks", StringUtil.Format(HelpDisplayStrings.GetLatestHelpContentWithoutHelpUri, cmdletName)));735 }736 else737 {738 obj.Properties.Add(new PSNoteProperty("remarks", StringUtil.Format(HelpDisplayStrings.GetLatestHelpContent, cmdletName, helpUri)));739 }740 }741 742 /// <summary>743 /// Adds the related links properties.744 /// </summary>745 /// <param name="obj"></param>746 /// <param name="relatedLink"></param>747 internal static void AddRelatedLinksProperties(PSObject obj, string relatedLink)748 {749 if (!string.IsNullOrEmpty(relatedLink))750 {751 PSObject navigationLinkObj = new PSObject();752 753 navigationLinkObj.TypeNames.Clear();754 navigationLinkObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#navigationLinks"));755 756 navigationLinkObj.Properties.Add(new PSNoteProperty("uri", relatedLink));757 758 List<PSObject> navigationLinkValues = new List<PSObject> { navigationLinkObj };759 760 // check if obj already has relatedLinks property761 PSNoteProperty relatedLinksPO = obj.Properties["relatedLinks"] as PSNoteProperty;762 if ((relatedLinksPO != null) && (relatedLinksPO.Value != null))763 {764 PSObject relatedLinksValue = PSObject.AsPSObject(relatedLinksPO.Value);765 PSNoteProperty navigationLinkPO = relatedLinksValue.Properties["navigationLink"] as PSNoteProperty;766 if ((navigationLinkPO != null) && (navigationLinkPO.Value != null))767 {768 PSObject navigationLinkValue = navigationLinkPO.Value as PSObject;769 if (navigationLinkValue != null)770 {771 navigationLinkValues.Add(navigationLinkValue);772 }773 else774 {775 PSObject[] navigationLinkValueArray = navigationLinkPO.Value as PSObject[];776 if (navigationLinkValueArray != null)777 {778 foreach (var psObject in navigationLinkValueArray)779 {780 navigationLinkValues.Add(psObject);781 }782 }783 }784 }785 }786 787 PSObject relatedLinksObj = new PSObject();788 789 relatedLinksObj.TypeNames.Clear();790 relatedLinksObj.TypeNames.Add(string.Create(CultureInfo.InvariantCulture, $"{DefaultCommandHelpObjectBuilder.TypeNameForDefaultHelp}#relatedLinks"));791 relatedLinksObj.Properties.Add(new PSNoteProperty("navigationLink", navigationLinkValues.ToArray()));792 793 obj.Properties.Add(new PSNoteProperty("relatedLinks", relatedLinksObj));794 }795 }796 797 /// <summary>798 /// Gets the parameter attribute from parameter metadata.799 /// </summary>800 /// <param name="attributes">Parameter attributes.</param>801 /// <returns>Collection of parameter attributes.</returns>802 private static Collection<ParameterAttribute> GetParameterAttribute(Collection<Attribute> attributes)803 {804 Collection<ParameterAttribute> paramAttributes = new Collection<ParameterAttribute>();805 806 foreach (Attribute attribute in attributes)807 {808 ParameterAttribute paramAttribute = (object)attribute as ParameterAttribute;809 810 if (paramAttribute != null)811 {812 paramAttributes.Add(paramAttribute);813 }814 }815 816 return paramAttributes;817 }818 819 /// <summary>820 /// Gets the validate set attribute from parameter metadata.821 /// </summary>822 /// <param name="attributes">Parameter attributes.</param>823 /// <returns>Collection of parameter attributes.</returns>824 private static Collection<ValidateSetAttribute> GetValidateSetAttribute(Collection<Attribute> attributes)825 {826 Collection<ValidateSetAttribute> validateSetAttributes = new Collection<ValidateSetAttribute>();827 828 foreach (Attribute attribute in attributes)829 {830 ValidateSetAttribute validateSetAttribute = (object)attribute as ValidateSetAttribute;831 832 if (validateSetAttribute != null)833 {834 validateSetAttributes.Add(validateSetAttribute);835 }836 }837 838 return validateSetAttributes;839 }840 841 /// <summary>842 /// Gets the pipeline input type.843 /// </summary>844 /// <param name="paramAttrib">Parameter attribute.</param>845 /// <returns>Pipeline input type.</returns>846 private static string GetPipelineInputString(ParameterAttribute paramAttrib)847 {848 Debug.Assert(paramAttrib != null);849 850 ArrayList values = new ArrayList();851 852 if (paramAttrib.ValueFromPipeline)853 {854 values.Add(StringUtil.Format(HelpDisplayStrings.PipelineByValue));855 }856 857 if (paramAttrib.ValueFromPipelineByPropertyName)858 {859 values.Add(StringUtil.Format(HelpDisplayStrings.PipelineByPropertyName));860 }861 862 if (paramAttrib.ValueFromRemainingArguments)863 {864 values.Add(StringUtil.Format(HelpDisplayStrings.PipelineFromRemainingArguments));865 }866 867 if (values.Count == 0)868 {869 return StringUtil.Format(HelpDisplayStrings.FalseShort);870 }871 872 StringBuilder sb = new StringBuilder();873 874 sb.Append(StringUtil.Format(HelpDisplayStrings.TrueShort));875 sb.Append(" (");876 877 for (int i = 0; i < values.Count; i++)878 {879 sb.Append((string)values[i]);880 881 if (i != (values.Count - 1))882 {883 sb.Append(", ");884 }885 }886 887 sb.Append(')');888 889 return sb.ToString();890 }891 892 /// <summary>893 /// Checks if a set of parameters contains any of the common parameters.894 /// </summary>895 /// <param name="parameters">Parameters to check.</param>896 /// <returns>True if it contains common parameters, false otherwise.</returns>897 internal static bool HasCommonParameters(Dictionary<string, ParameterMetadata> parameters)898 {899 Collection<string> commonParams = new Collection<string>();900 901 foreach (KeyValuePair<string, ParameterMetadata> parameter in parameters)902 {903 if (Cmdlet.CommonParameters.Contains(parameter.Value.Name))904 {905 commonParams.Add(parameter.Value.Name);906 }907 }908 909 return (commonParams.Count == Cmdlet.CommonParameters.Count);910 }911 912 /// <summary>913 /// Checks if the module contains HelpInfoUri.914 /// </summary>915 /// <param name="module"></param>916 /// <param name="moduleName"></param>917 /// <returns></returns>918 private static bool HasHelpInfoUri(PSModuleInfo module, string moduleName)919 {920 // The core module is really a SnapIn, so module will be null921 if (!string.IsNullOrEmpty(moduleName) && moduleName.Equals(InitialSessionState.CoreModule, StringComparison.OrdinalIgnoreCase))922 {923 return true;924 }925 926 if (module == null)927 {928 return false;929 }930 931 return !string.IsNullOrEmpty(module.HelpInfoUri);932 }933 }934}935 