PowerShell by default generates most of the help text for cmdlets in binary modules in an expected way except for the Cmdlet Description,synopsis and related links. Just for specifying the cmdlet synopsis, description,related links looks like we need to generate the whole help text in MAML format. Is there a way to specify Cmdlet description,synopsis, related links as an Attribute in c# source code like we specify the output type?
[Cmdlet("Get", "Greeting")]
[OutputType(string)]
public class GetGreeting : PSCmdlet
{
[Parameter(Mandatory = false, ValueFromPipelineByPropertyName = true, HelpMessage = @"Person's name")]
public string Name { get; set; }
}
Not currently, although it's not impossible to implement, it would just need changes to the help documentation to go looking for additional attributes or attribute properties for help content.
Currently the most "straightforward" way I've found to go about it is with the PlatyPS module; it can generate a Markdown file with your cmdlet name and parameters that you can fill out with help information, and then it will generate a MAML file to put in the module from the Markdown. There are still a handful of odd edge cases and it's a bit weird to get used to working with, but on the whole it's a ton easier than hand-crafting MAML.
Can this be taken up as a new feature request if native help documentation support for this does not exist?
What about localization? I do not think this is the right way.
The suggestion is interesting for sure and I agree that it could be helpful. Localization is the primary reason to have downloadable help in MAML.
Look at the following example of help for Get-Process
. As you can see the description and related link blocks can get very long. It would just make the C# code look messy. Though adding a attribute property for Synopsis could be fine. Still MAML / PlatyPS is the right way to go as it also allows you to specify examples, which I believe are most useful.
NAME
Get-Process
SYNOPSIS
Gets the processes that are running on the local computer.
SYNTAX
Get-Process [[-Name] <String[]>] [-FileVersionInfo] [-Module] [<CommonParameters>]
Get-Process [-FileVersionInfo] -Id <Int32[]> [-Module] [<CommonParameters>]
Get-Process [-FileVersionInfo] -InputObject <Process[]> [-Module] [<CommonParameters>]
Get-Process -Id <Int32[]> -IncludeUserName [<CommonParameters>]
Get-Process [[-Name] <String[]>] -IncludeUserName [<CommonParameters>]
Get-Process -IncludeUserName -InputObject <Process[]> [<CommonParameters>]
DESCRIPTION
The `Get-Process` cmdlet gets the processes on a local computer.
Without parameters, this cmdlet gets all of the processes on the local computer. You can also specify a particular
process by process name or process ID (PID) or pass a process object through the pipeline to this cmdlet.
By default, this cmdlet returns a process object that has detailed information about the process and supports
methods that let you start and stop the process. You can also use the parameters of the `Get-Process` cmdlet to
get file version information for the program that runs in the process and to get the modules that the process
loaded.
RELATED LINKS
Online Version: https://docs.microsoft.com/powershell/module/microsoft.powershell.management/get-process?view=power
shell-7&WT.mc_id=ps-gethelp
Debug-Process
Get-Process
Start-Process
Stop-Process
Wait-Process
@adityapatwardhan PlatyPS is good if you want many changes. We are happy with the default PowerShell Help except we need one or 2 additional sections. We generate code for our cmdlets so it wouldn't be a big deal for us to include these as attributes in our code irrespective of how unwieldy those attributes look.
While using PlatyPS, we are having to go through multiple steps - Generate MD files from PlatyPS; those MD files have sections which are not complete. Generate some intermediate XML files with the info that we need to populate the MD files empty sections generated by PlatyPS. Use these MD files to finally patch the MAML files that we need for help text. The MAML files are missing the Synopsis section (probably due to a bug in PlatyPS that we have filed with them).
If the above feature that we are asking for was supported, we had much simpler process for help text generation.
If the above feature that we are asking for was supporting, we had much simpler process for help text generation.
Current HelpSystem was designed many years ago. Since then, much has changed. We have already discussed that this system should be modernized. Unfortunately, MSFT team has not yet published a public roadmap.
There was an idea to exclude MAML altogether.
Now I think we could use ideas from new PowerShellGet 3.0 for HelpSystem too.
This would dramatically simplify the help creation and support.
Just to tack on to this, C# doc comments allow any XML within them. This can then be parsed out at build time, so you could also document something like this:
/// <powershell-help>
/// <description>
/// The `Get-Process` cmdlet gets the processes on a local computer.
///
/// Without parameters, this cmdlet gets all of the processes on the local computer. You can also specify a particular
/// process by process name or process ID (PID) or pass a process object through the pipeline to this cmdlet.
///
/// By default, this cmdlet returns a process object that has detailed information about the process and supports
/// methods that let you start and stop the process. You can also use the parameters of the `Get-Process` cmdlet to
/// get file version information for the program that runs in the process and to get the modules that the process
/// loaded.
/// </description>
/// </powershell-help>
[Cmdlet(VerbsCommon.Get, "Process")]
public class GetProcessCommand : PSCmdlet
{
...
}
Pros:
Cons:
The essential issue for attributes is that it's hard to structure strings provided as arguments to them. One solution to that is to use a resource file. For example, something I'm working on for PSScriptAnalyzer:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public sealed class RuleAttribute : ScriptAnalyzerAttribute
{
private readonly Lazy<string> _descriptionLazy;
public RuleAttribute(string name, string description)
{
Name = name;
_descriptionLazy = new Lazy<string>(() => description);
}
public RuleAttribute(string name, Type descriptionResourceProvider, string descriptionResourceKey)
{
Name = name;
_descriptionLazy = new Lazy<string>(() => GetStringFromResourceProvider(descriptionResourceProvider, descriptionResourceKey));
}
public string Name { get; }
public DiagnosticSeverity Severity { get; set; } = DiagnosticSeverity.Warning;
public string Namespace { get; set; }
public string Description => _descriptionLazy.Value;
private static string GetStringFromResourceProvider(Type resourceProvider, string resourceKey)
{
PropertyInfo resourceProperty = resourceProvider.GetProperty(resourceKey, BindingFlags.Static | BindingFlags.NonPublic);
return (string)resourceProperty.GetValue(null);
}
}
One solution to that is to use a resource file.
And we fall to an design with an external file. In the case it is better to think about an universal format which can be used for both script and binary cmdlets. And I'd expect that the universal format is Markdown :-) This dramatically simplify HelpSystem.
And we fall to an design with an external file
Yeah I think anything with localisation support is going to need to separate implementation from documentation, and markdown is a better way to go on that
Most helpful comment
And we fall to an design with an external file. In the case it is better to think about an universal format which can be used for both script and binary cmdlets. And I'd expect that the universal format is Markdown :-) This dramatically simplify HelpSystem.