1

I have a PowerShell function in a .ps1 file. The function has two parameter sets with one parameter each. The param() block in the function declaration is:

Function Restore-ExplorerWindow
{
    param(
        [Parameter(ParameterSetName = 'ByPath',
            Mandatory,
            Position=0,
            ValueFromPipeline)]
        [ValidateScript({Test-Path $_ -PathType 'Leaf'})]
        [String[]]
        $Path,
        [Parameter(ParameterSetName = 'ByObject',
            Mandatory,
            Position=0,
            ValueFromPipeline)]
        [System.Object[]]
        $ExplorerState
    )

Without any help defined, PowerShell generates the following:

SYNTAX
    Restore-ExplorerWindow [-Path] <string[]>  [<CommonParameters>]

    Restore-ExplorerWindow [-ExplorerState] <Object[]>  [<CommonParameters>]


PARAMETERS
    -ExplorerState <Object[]>

        Required?                    true
        Position?                    0
        Accept pipeline input?       true (ByValue)
        Parameter set name           ByObject
        Aliases                      None
        Dynamic?                     false

    -Path <string[]>

        Required?                    true
        Position?                    0
        Accept pipeline input?       true (ByValue)
        Parameter set name           ByPath
        Aliases                      None
        Dynamic?                     false

But when I specify a seemingly functional .xml help file, which has the following SYNTAX and PARAMETERS nodes:

    <command:syntax>
      <command:syntaxItem>
        <maml:name>Restore-ExplorerWindow</maml:name>
        <command:parameter
         required="true"
         variableLength="true"
         globbing="false"
         pipelineInput="true"
         position="0"
         aliases="none">
          <maml:name>Path</maml:name>
          <dev:type>
            <maml:name>System.String[]</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>none</dev:defaultValue>
        </command:parameter>
      </command:syntaxItem>
      <command:syntaxItem>
        <maml:name>Restore-ExplorerWindow</maml:name>
        <command:parameter
         required="true"
         variableLength="true"
         globbing="false"
         pipelineInput="true"
         position="0"
         aliases="none">
          <maml:name>ExplorerState</maml:name>
          <dev:type>
            <maml:name>System.Object[]</maml:name>
            <maml:uri />
          </dev:type>
          <dev:defaultValue>none</dev:defaultValue>
        </command:parameter>
      </command:syntaxItem>
     </command:syntax>
    <command:parameters>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="true" position="0" aliases="none">
        <maml:name>Path</maml:name>
        <maml:description>
          <maml:para>Path to previously exported .xml file.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="true">System.String[]</command:parameterValue>
        <dev:type>
          <maml:name>System.String[]</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>none</dev:defaultValue>
      </command:parameter>
      <command:parameter required="true" variableLength="true" globbing="false" pipelineInput="true" position="0" aliases="none">
        <maml:name>ExplorerState</maml:name>
        <maml:description>
          <maml:para>Custom object created by `Get-ExplorerWindow`.</maml:para>
        </maml:description>
        <command:parameterValue required="true" variableLength="true">System.Object[]</command:parameterValue>
        <dev:type>
          <maml:name>System.Object[]</maml:name>
          <maml:uri />
        </dev:type>
        <dev:defaultValue>none</dev:defaultValue>
      </command:parameter>
    </command:parameters>

Get-Help displays the following:

SYNTAX
    Restore-ExplorerWindow [-Path] [<CommonParameters>]

    Restore-ExplorerWindow [-ExplorerState] [<CommonParameters>]


DESCRIPTION
    Opens an Explorer window using the information saved by `Get-ExplorerWindow`.


PARAMETERS
    -Path <System.String[]>
        Path to previously exported .xml file.

        Required?                    true
        Position?                    0
        Default value                none
        Accept pipeline input?       true
        Accept wildcard characters?  false

    -ExplorerState <Object[]>
        Custom object created by `Get-ExplorerWindow`.

        Required?                    true
        Position?                    0
        Default value                none
        Accept pipeline input?       true
        Accept wildcard characters?  false

I can't figure out why I'm not seeing:

SYNTAX
    Restore-ExplorerWindow [-Path] <string[]>  [<CommonParameters>]

    Restore-ExplorerWindow [-ExplorerState] <Object[]>  [<CommonParameters>]

with the xml help.

mklement0
  • 382,024
  • 64
  • 607
  • 775
Keith Miller
  • 702
  • 5
  • 13
  • As an aside: your function won't work as intended with a positional `[string]` argument, because it is a type match for _both_ parameter sets. – mklement0 Oct 14 '22 at 20:03
  • 1
    However, you can fix this by placing `[CmdletBinding(DefaultParameterSetName = 'ByPath')]` above the `param(...)` block. – mklement0 Oct 14 '22 at 20:08
  • 1
    Thank you for that. Hadn't run into the issue during earlier testing, but did get the "...ambiguous ParameterSet..." error and this fixed it. – Keith Miller Oct 15 '22 at 00:00

1 Answers1

1

Your <command:syntaxItem> elements are each missing a <command:parameterValue> child element.

Simply duplicate the elements of that name already defined later as <command:parameter> child elements.

The documentation of the XML-based MAML format PowerShell help files use is How to Create the Cmdlet Help File


You can avoid the problem you encountered - notably the need to duplicate information across elements - by authoring your help files with the help of the PlatyPS module (install with Install-Module PlatyPS), which auto-generates the MAML XML from Markdown files that it scaffolds from a given module's implementation.


Note:

  • The PlatyPs module only works with PowerShell modules, not stand-alone PowerShell scripts (.ps1 files).

  • For script files (.ps1) / functions contained in script files, the simplest approach is to use comment-based help definitions rather than external MAML files (.help-xml).

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • I read about the module, but wanted to familiarize myself with to file format fist, for precisely this level of comprehension. – Keith Miller Oct 14 '22 at 22:03
  • @KeithMiller, this answer tells you how to fix your MAML, which is what your question is about. It also points you to a superior alternative that saves you from having to know the MAML details, but I've also just added a link to the documentation that describes those details. Let us know if you think something is still missing. – mklement0 Oct 14 '22 at 22:37
  • Had to do non-computer things before I could test. I had read the linked "How to..." article, which didn't have the level of detail I needed. I'm also slow editing because I'm legaaly blind. But now that i've had a chance to edit & test --- everything is great. Marking as `Answer` and upvoting... Don't be so impatient!!! :D – Keith Miller Oct 15 '22 at 00:25
  • Also, when I checked out `PlatyPS` earlier, I got the impression I needed a `.psm1` file. My script is just a `.ps1` file.... – Keith Miller Oct 15 '22 at 00:34
  • Sorry, @KeithMiller - didn't mean to be impatient; just wasn't sure what to make of your initial feedback. Glad to hear it helped. Yes, `PlatyPS` only works with _modules_. For scripts (`.ps1`) / functions contained in scripts, it's easier to use _comment-based_ help; please see my update. – mklement0 Oct 15 '22 at 01:40
  • 2
    I also forgot to explicitly say "Thank you", so thank you. I've created comment-based help before, and started to for this and it's companion function. But with fleshed-out examples, it can start to get longer than the code itself, and the zoom levels demanded by my vision issues make it easy to get lost, so I decided to learn about xml help files, and I'm off to a good start with your help. Rather than return to comment-based help, I think it's time to learn about modules! :D – Keith Miller Oct 15 '22 at 02:35
  • :) Glad to hear it, @KeithMiller. – mklement0 Oct 15 '22 at 02:38