Wednesday, December 24, 2014

PowerShell Help File Authoring Woes

Poor Documentation

I was really hoping to write some killer help for (my cmdlets)[https://github.com/Swoogan/Octopus-Cmdlets], but I did not know where to start. If you search around the web and MSDN you might find the only two “helpful” files:
http://msdn.microsoft.com/en-us/library/dd878343(v=vs.85).aspx
and
http://msdn.microsoft.com/en-us/library/bb525433(v=vs.85).aspx

I was not able to find anything in the way of blogs or community documentation. There are bits and pieces, here and there, but they are mostly geared toward advanced functions (script cmdlets).

Note that there are several flaws in the second article that held me up quite a bit. For one, they say to “add the following XML headers to the text file” and list <helpItems xmlns="http://msh" schema="maml">. This is not a header. It is an opening tag that needs to be closed at the end of the document. Second, the example does not show either of the “headers”. Would it kill them to ever give an example that is complete? Finally, the page does not indicate where this file should be saved, nor does it link to the separate document that does (the first one).

Writing a Sane Example

I do not know why it would be so hard to write:

Save the following file to SampleModule\en-US\SampleModule.dll-help.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <helpItems xmlns="http://msh" schema="maml">
      <command:command xmlns:maml="http://schemas.microsoft.com/maml/2004/10" xmlns:command="http://schemas.microsoft.com/maml/dev/command/2004/10" xmlns:dev="http://schemas.microsoft.com/maml/dev/2004/10">
        <command:details>
          <command:name>Get-Something</command:name>
          <command:verb>Get</command:verb>
          <command:noun>Something</command:noun>          
          <maml:description>
            <maml:para>Gets one or more somethings.</maml:para>
          </maml:description>
        </command:details>
      </command:command>
    </helpItems>

I am not sure what the redundant name, verb, and noun nonsense is about.

And it All Goes Downhill

When I started researching I was ecstatic to learn that the format is XML. I was so looking forward to writing 100% more tags than text. Remember, it is always a good idea to make writing documentation more of a pain than it already is. There is nothing like a boatload of friction to motivate people.

Oh well, after way too much time fighting the bad documentation I finally got my help file to load. What an achievement!

Here is what the system generated documentation looks like (aka no help file):

NAME
Get-Something

SYNTAX
Get-Something [[-Name] <string[]>] [<CommonParameters>]

Get-Something -Id <Int32[]> [<CommonParameters>]

And with my file:

NAME
Get-Something

SYNOPSIS
Gets one or more somethings.

SYNTAX

DESCRIPTION

RELATED LINKS

Hey, what the heck happened to my SYNTAX??? Really? If I do not define it, it goes away? REALLY???

Once again Microsoft forces you into an all-or-nothing proposition. Want to add SYSNOPSIS fields to all your cmdlets? Boom! All your SYNTAX descriptors are gone. But the SYNTAX was perfect the way it was!!!

Good thing making documentation is so much fun, or I might have started to get discouraged at that point.

WTF???

Well the only thing left to do is find out how to document the syntax. All I wanted to do was add a synopsis to each (for now) but lets see what it would take to bring this up to snuff. Here is the document on writing syntax:
http://msdn.microsoft.com/en-us/library/bb525442(v=vs.85).aspx

That is right boys and girls, you have to take all the cmdlets, in all their variations and meticulously write XML to define the usage. Were you thinking you could maybe just copy the generated output to a syntax element like so?

<command:syntax>Get-Something [[-Name] <string[]>]  [<CommonParameters>]</command:syntax>

Hahahahahahahaha hahaha haha ha…

The best part is the you get to keep your documentation sync every time you change your cmdlets. Now I am faced with a dilema:

  1. Release my young and rapidly changing project with no documentation.
  2. Write the documentation now and have to change it over and over as the API matures.

What wonderful options.

For the record, this is what the syntax XML looks like for a single variation of a single command:

   <command:syntax>
      <command:syntaxItem>
        <command:name>Invoke-psake</command:name>
        <command:parameter require="false" variableLength="false" globbing="false" pipelineInput="false" postion="0">
          <maml:name>buildFile</maml:name>
          <command:parameterValue required="false" variableLength="false">String</command:parameterValue>
        </command:parameter>
        <command:parameter require="false" variableLength="false" globbing="false" pipelineInput="false" postion="0">
          <maml:name>taskList</maml:name>
          <command:parameterValue required="false" variableLength="false">String[]</command:parameterValue>
        </command:parameter>
        <command:parameter require="false" variableLength="false" globbing="false" pipelineInput="false" postion="0">
          <maml:name>framework</maml:name>
          <command:parameterValue required="false" variableLength="false">String</command:parameterValue>
        </command:parameter>
        <command:parameter require="false" variableLength="false" globbing="false" pipelineInput="false" postion="0">
          <maml:name>docs</maml:name>         
          <command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
        </command:parameter>
        <command:parameter require="false" variableLength="false" globbing="false" pipelineInput="false" postion="0">
          <maml:name>parameters</maml:name>         
          <command:parameterValue required="false" variableLength="false">Hashtable</command:parameterValue>
        </command:parameter>
        <command:parameter require="false" variableLength="false" globbing="false" pipelineInput="false" postion="0">
          <maml:name>properties</maml:name>         
          <command:parameterValue required="false" variableLength="false">Hashtable</command:parameterValue>
        </command:parameter>
        <command:parameter require="false" variableLength="false" globbing="false" pipelineInput="false" postion="0">
          <maml:name>nologo</maml:name>         
          <command:parameterValue required="false" variableLength="false">SwitchParameter</command:parameterValue>
        </command:parameter>
     </command:syntaxItem>
   </command:syntax>

Taken from the psake help file.

Do not worry. They know there is a problem and are thinking about improving it. It is not like they are just going to totally ignore it for eight years or something.

And yes I will look into the PSCX module mentioned in that link, but in the meantime I am going to cry.

No comments:

Post a Comment