MegaBites-AI/Windows-powershell
0308
1// Copyright (c) Microsoft Corporation.2// Licensed under the MIT License.3 4using System.Diagnostics.CodeAnalysis;5using System.Text;6 7namespace System.Management.Automation8{9 /// <summary>10 /// A ProxyCommand class used to represent a Command constructed Dynamically.11 /// </summary>12 public sealed class ProxyCommand13 {14 #region Private Constructor15 16 /// <summary>17 /// Private Constructor to restrict inheritance.18 /// </summary>19 private ProxyCommand()20 {21 }22 23 #endregion24 25 #region Public Static Methods26 27 /// <summary>28 /// This method constructs a string representing the command specified by <paramref name="commandMetadata"/>.29 /// The returned string is a ScriptBlock which can be used to configure a Cmdlet/Function in a Runspace.30 /// </summary>31 /// <param name="commandMetadata">32 /// An instance of CommandMetadata representing a command.33 /// </param>34 /// <returns>35 /// A string representing Command ScriptBlock.36 /// </returns>37 /// <exception cref="ArgumentNullException">38 /// commandMetadata is null.39 /// </exception>40 public static string Create(CommandMetadata commandMetadata)41 {42 if (commandMetadata == null)43 {44 throw PSTraceSource.NewArgumentNullException("commandMetaData");45 }46 47 return commandMetadata.GetProxyCommand(string.Empty, true);48 }49 50 /// <summary>51 /// This method constructs a string representing the command specified by <paramref name="commandMetadata"/>.52 /// The returned string is a ScriptBlock which can be used to configure a Cmdlet/Function in a Runspace.53 /// </summary>54 /// <param name="commandMetadata">55 /// An instance of CommandMetadata representing a command.56 /// </param>57 /// <param name="helpComment">58 /// The string to be used as the help comment.59 /// </param>60 /// <returns>61 /// A string representing Command ScriptBlock.62 /// </returns>63 /// <exception cref="ArgumentNullException">64 /// commandMetadata is null.65 /// </exception>66 public static string Create(CommandMetadata commandMetadata, string helpComment)67 {68 if (commandMetadata == null)69 {70 throw PSTraceSource.NewArgumentNullException("commandMetaData");71 }72 73 return commandMetadata.GetProxyCommand(helpComment, true);74 }75 76 /// <summary>77 /// This method constructs a string representing the command specified by <paramref name="commandMetadata"/>.78 /// The returned string is a ScriptBlock which can be used to configure a Cmdlet/Function in a Runspace.79 /// </summary>80 /// <param name="commandMetadata">81 /// An instance of CommandMetadata representing a command.82 /// </param>83 /// <param name="helpComment">84 /// The string to be used as the help comment.85 /// </param>86 /// <param name="generateDynamicParameters">87 /// A boolean that determines whether the generated proxy command should include the functionality required88 /// to proxy dynamic parameters of the underlying command.89 /// </param>90 /// <returns>91 /// A string representing Command ScriptBlock.92 /// </returns>93 /// <exception cref="ArgumentNullException">94 /// commandMetadata is null.95 /// </exception>96 public static string Create(CommandMetadata commandMetadata, string helpComment, bool generateDynamicParameters)97 {98 if (commandMetadata == null)99 {100 throw PSTraceSource.NewArgumentNullException("commandMetaData");101 }102 103 return commandMetadata.GetProxyCommand(helpComment, generateDynamicParameters);104 }105 106 /// <summary>107 /// This method constructs a string representing the CmdletBinding attribute of the command108 /// specified by <paramref name="commandMetadata"/>.109 /// </summary>110 /// <param name="commandMetadata">111 /// An instance of CommandMetadata representing a command.112 /// </param>113 /// <returns>114 /// A string representing the CmdletBinding attribute of the command.115 /// </returns>116 /// <exception cref="ArgumentNullException">117 /// commandMetadata is null.118 /// </exception>119 public static string GetCmdletBindingAttribute(CommandMetadata commandMetadata)120 {121 if (commandMetadata == null)122 {123 throw PSTraceSource.NewArgumentNullException("commandMetaData");124 }125 126 return commandMetadata.GetDecl();127 }128 129 /// <summary>130 /// This method constructs a string representing the param block of the command131 /// specified by <paramref name="commandMetadata"/>. The returned string only contains the132 /// parameters, it is not enclosed in "param()".133 /// </summary>134 /// <param name="commandMetadata">135 /// An instance of CommandMetadata representing a command.136 /// </param>137 /// <returns>138 /// A string representing the parameters of the command.139 /// </returns>140 /// <exception cref="ArgumentNullException">141 /// commandMetadata is null.142 /// </exception>143 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]144 public static string GetParamBlock(CommandMetadata commandMetadata)145 {146 if (commandMetadata == null)147 {148 throw PSTraceSource.NewArgumentNullException("commandMetaData");149 }150 151 return commandMetadata.GetParamBlock();152 }153 154 /// <summary>155 /// This method constructs a string representing the begin block of the command156 /// specified by <paramref name="commandMetadata"/>. The returned string only contains the157 /// script, it is not enclosed in "begin { }".158 /// </summary>159 /// <param name="commandMetadata">160 /// An instance of CommandMetadata representing a command.161 /// </param>162 /// <returns>163 /// A string representing the begin block of the command.164 /// </returns>165 /// <exception cref="ArgumentNullException">166 /// commandMetadata is null.167 /// </exception>168 public static string GetBegin(CommandMetadata commandMetadata)169 {170 if (commandMetadata == null)171 {172 throw PSTraceSource.NewArgumentNullException("commandMetaData");173 }174 175 return commandMetadata.GetBeginBlock();176 }177 178 /// <summary>179 /// This method constructs a string representing the process block of the command180 /// specified by <paramref name="commandMetadata"/>. The returned string only contains the181 /// script, it is not enclosed in "process { }".182 /// </summary>183 /// <param name="commandMetadata">184 /// An instance of CommandMetadata representing a command.185 /// </param>186 /// <returns>187 /// A string representing the process block of the command.188 /// </returns>189 /// <exception cref="ArgumentNullException">190 /// commandMetadata is null.191 /// </exception>192 public static string GetProcess(CommandMetadata commandMetadata)193 {194 if (commandMetadata == null)195 {196 throw PSTraceSource.NewArgumentNullException("commandMetaData");197 }198 199 return commandMetadata.GetProcessBlock();200 }201 202 /// <summary>203 /// This method constructs a string representing the dynamic parameter block of the command204 /// specified by <paramref name="commandMetadata"/>. The returned string only contains the205 /// script, it is not enclosed in "dynamicparam { }".206 /// </summary>207 /// <param name="commandMetadata">208 /// An instance of CommandMetadata representing a command.209 /// </param>210 /// <returns>211 /// A string representing the dynamic parameter block of the command.212 /// </returns>213 /// <exception cref="ArgumentNullException">214 /// commandMetadata is null.215 /// </exception>216 public static string GetDynamicParam(CommandMetadata commandMetadata)217 {218 if (commandMetadata == null)219 {220 throw PSTraceSource.NewArgumentNullException("commandMetaData");221 }222 223 return commandMetadata.GetDynamicParamBlock();224 }225 226 /// <summary>227 /// This method constructs a string representing the end block of the command228 /// specified by <paramref name="commandMetadata"/>. The returned string only contains the229 /// script, it is not enclosed in "end { }".230 /// </summary>231 /// <param name="commandMetadata">232 /// An instance of CommandMetadata representing a command.233 /// </param>234 /// <returns>235 /// A string representing the end block of the command.236 /// </returns>237 /// <exception cref="ArgumentNullException">238 /// commandMetadata is null.239 /// </exception>240 public static string GetEnd(CommandMetadata commandMetadata)241 {242 if (commandMetadata == null)243 {244 throw PSTraceSource.NewArgumentNullException("commandMetaData");245 }246 247 return commandMetadata.GetEndBlock();248 }249 250 /// <summary>251 /// This method constructs a string representing the clean block of the command252 /// specified by <paramref name="commandMetadata"/>. The returned string only contains the253 /// script, it is not enclosed in "clean { }".254 /// </summary>255 /// <param name="commandMetadata">256 /// An instance of CommandMetadata representing a command.257 /// </param>258 /// <returns>259 /// A string representing the end block of the command.260 /// </returns>261 /// <exception cref="ArgumentNullException">262 /// If <paramref name="commandMetadata"/> is null.263 /// </exception>264 public static string GetClean(CommandMetadata commandMetadata)265 {266 if (commandMetadata == null)267 {268 throw PSTraceSource.NewArgumentNullException(nameof(commandMetadata));269 }270 271 return commandMetadata.GetCleanBlock();272 }273 274 private static T GetProperty<T>(PSObject obj, string property) where T : class275 {276 T result = null;277 if (obj != null && obj.Properties[property] != null)278 {279 result = obj.Properties[property].Value as T;280 }281 282 return result;283 }284 285 private static string GetObjText(object obj)286 {287 string text = null;288 289 PSObject psobj = obj as PSObject;290 if (psobj != null)291 {292 text = GetProperty<string>(psobj, "Text");293 }294 295 return text ?? obj.ToString();296 }297 298 private static void AppendContent(StringBuilder sb, string section, object obj)299 {300 if (obj != null)301 {302 string text = GetObjText(obj);303 if (!string.IsNullOrEmpty(text))304 {305 sb.Append('\n');306 sb.Append(section);307 sb.Append("\n\n");308 sb.Append(text);309 sb.Append('\n');310 }311 }312 }313 314 private static void AppendContent(StringBuilder sb, string section, PSObject[] array)315 {316 if (array != null)317 {318 bool first = true;319 foreach (PSObject obj in array)320 {321 string text = GetObjText(obj);322 if (!string.IsNullOrEmpty(text))323 {324 if (first)325 {326 first = false;327 sb.Append("\n\n");328 sb.Append(section);329 sb.Append("\n\n");330 }331 332 sb.Append(text);333 sb.Append('\n');334 }335 }336 337 if (!first)338 {339 sb.Append('\n');340 }341 }342 }343 344 private static void AppendType(StringBuilder sb, string section, PSObject parent)345 {346 PSObject type = GetProperty<PSObject>(parent, "type");347 PSObject name = GetProperty<PSObject>(type, "name");348 if (name != null)349 {350 sb.Append("\n\n");351 sb.Append(section);352 sb.Append("\n\n");353 sb.Append(GetObjText(name));354 sb.Append('\n');355 }356 else357 {358 PSObject uri = GetProperty<PSObject>(type, "uri");359 if (uri != null)360 {361 sb.Append("\n\n");362 sb.Append(section);363 sb.Append("\n\n");364 sb.Append(GetObjText(uri));365 sb.Append('\n');366 }367 }368 }369 370 /// <summary>371 /// Construct the text that can be used in a multi-line comment for get-help.372 /// </summary>373 /// <param name="help">A custom PSObject created by Get-Help.</param>374 /// <returns>A string that can be used as the help comment for script for the input HelpInfo object.</returns>375 /// <exception cref="System.ArgumentNullException">When the help argument is null.</exception>376 /// <exception cref="System.InvalidOperationException">When the help argument is not recognized as a HelpInfo object.</exception>377 public static string GetHelpComments(PSObject help)378 {379 ArgumentNullException.ThrowIfNull(help);380 381 bool isHelpObject = false;382 foreach (string typeName in help.InternalTypeNames)383 {384 if (typeName.Contains("HelpInfo"))385 {386 isHelpObject = true;387 break;388 }389 }390 391 if (!isHelpObject)392 {393 string error = ProxyCommandStrings.HelpInfoObjectRequired;394 throw new InvalidOperationException(error);395 }396 397 StringBuilder sb = new StringBuilder();398 399 AppendContent(sb, ".SYNOPSIS", GetProperty<string>(help, "Synopsis"));400 AppendContent(sb, ".DESCRIPTION", GetProperty<PSObject[]>(help, "Description"));401 402 PSObject parameters = GetProperty<PSObject>(help, "Parameters");403 PSObject[] parameter = GetProperty<PSObject[]>(parameters, "Parameter");404 if (parameter != null)405 {406 foreach (PSObject param in parameter)407 {408 PSObject name = GetProperty<PSObject>(param, "Name");409 PSObject[] description = GetProperty<PSObject[]>(param, "Description");410 sb.Append("\n.PARAMETER ");411 sb.Append(name);412 sb.Append("\n\n");413 foreach (PSObject obj in description)414 {415 string text = GetProperty<string>(obj, "Text") ?? obj.ToString();416 if (!string.IsNullOrEmpty(text))417 {418 sb.Append(text);419 sb.Append('\n');420 }421 }422 }423 }424 425 PSObject examples = GetProperty<PSObject>(help, "examples");426 PSObject[] example = GetProperty<PSObject[]>(examples, "example");427 if (example != null)428 {429 foreach (PSObject ex in example)430 {431 StringBuilder exsb = new StringBuilder();432 433 PSObject[] introduction = GetProperty<PSObject[]>(ex, "introduction");434 if (introduction != null)435 {436 foreach (PSObject intro in introduction)437 {438 if (intro != null)439 {440 exsb.Append(GetObjText(intro));441 }442 }443 }444 445 PSObject code = GetProperty<PSObject>(ex, "code");446 if (code != null)447 {448 exsb.Append(code.ToString());449 }450 451 PSObject[] remarks = GetProperty<PSObject[]>(ex, "remarks");452 if (remarks != null)453 {454 exsb.Append('\n');455 foreach (PSObject remark in remarks)456 {457 string remarkText = GetProperty<string>(remark, "text");458 exsb.Append(remarkText);459 }460 }461 462 if (exsb.Length > 0)463 {464 sb.Append("\n\n.EXAMPLE\n\n");465 sb.Append(exsb);466 }467 }468 }469 470 PSObject alertSet = GetProperty<PSObject>(help, "alertSet");471 AppendContent(sb, ".NOTES", GetProperty<PSObject[]>(alertSet, "alert"));472 473 PSObject inputtypes = GetProperty<PSObject>(help, "inputTypes");474 PSObject inputtype = GetProperty<PSObject>(inputtypes, "inputType");475 AppendType(sb, ".INPUTS", inputtype);476 477 PSObject returnValues = GetProperty<PSObject>(help, "returnValues");478 PSObject returnValue = GetProperty<PSObject>(returnValues, "returnValue");479 AppendType(sb, ".OUTPUTS", returnValue);480 481 PSObject relatedLinks = GetProperty<PSObject>(help, "relatedLinks");482 PSObject[] navigationLink = GetProperty<PSObject[]>(relatedLinks, "navigationLink");483 if (navigationLink != null)484 {485 foreach (PSObject link in navigationLink)486 {487 // Most likely only one of these will append anything, but it488 // isn't wrong to append them both.489 AppendContent(sb, ".LINK", GetProperty<PSObject>(link, "uri"));490 AppendContent(sb, ".LINK", GetProperty<PSObject>(link, "linkText"));491 }492 }493 494 AppendContent(sb, ".COMPONENT", GetProperty<PSObject>(help, "Component"));495 AppendContent(sb, ".ROLE", GetProperty<PSObject>(help, "Role"));496 AppendContent(sb, ".FUNCTIONALITY", GetProperty<PSObject>(help, "Functionality"));497 498 return sb.ToString();499 }500 501 #endregion502 }503}504 