Nigel Boulton's Blog
7May/1125

Problems with PowerShell Comment-based Help

I was writing a script recently and came across a couple of "gotchas" when attempting to use PowerShell 2's Comment-based Help at script level. A simple test script to demonstrate what I am about to describe is shown below:

<#
.SYNOPSIS
    Tests whether PowerShell 2 Comment-based Help is working as expected
.DESCRIPTION
    Displays Comment-based Help for this script
.EXAMPLE
    Test-CommentBasedHelp.ps1
.NOTES
    None
#>            
Write-Host "Hello World"


The expected output from this is as follows:

Expected output from test script showing Comment-based Help working

"Get-Help about_comment_based_help" says

"SYNTAX FOR COMMENT-BASED HELP IN SCRIPTS

  Comment-based Help for a script can appear in one of the following two

  locations in the script.

  -- At the beginning of the script file. Script Help can be preceded in the 
     script only by comments and blank lines.

  -- If the first item in the script body (after the Help) is a function 
     declaration, there must be at least two blank lines between the end of the 
     script Help and the function declaration. Otherwise, the Help is 
     interpreted as being Help for the function, not Help for the script.

  -- At the end of the script file."

Looks straightforward enough. However, if you try the following:

# Comment            
<#
.SYNOPSIS
    Tests whether PowerShell 2 Comment-based Help is working as expected
.DESCRIPTION
    Displays Comment-based Help for this script
.EXAMPLE
    Test-CommentBasedHelp.ps1
.NOTES
    None
#>            
Write-Host "Hello World"

The output isn't as expected. You just get the name of the script returned, as shown below:

Output from test script showing just script name returned

What's that about…? Well, this is the first "gotcha". Although Get-Help says that Script Help can be preceded in the script by comments and blank lines, it's easy to miss the text further up that says

"All of the lines in a comment-based Help topic must be contiguous. If a comment-based Help topic follows a comment that is not part of the Help topic, there must be at least one blank line between the last non-Help comment line and the beginning of the comment-based Help."

So to avoid breaking it, you need to use the following syntax:

# Comment            

<#
.SYNOPSIS
    Tests whether PowerShell 2 Comment-based Help is working as expected
.DESCRIPTION
    Displays Comment-based Help for this script
.EXAMPLE
    Test-CommentBasedHelp.ps1
.NOTES
    None
#>            
Write-Host "Hello World"

One tiny blank line can make such a difference!

The same applies if you put anything inside the comment block before the first keyword. For example, the following is not valid:

<#
Comment
.SYNOPSIS
    Tests whether PowerShell 2 Comment-based Help is working as expected
.DESCRIPTION
    Displays Comment-based Help for this script
.EXAMPLE
    Test-CommentBasedHelp.ps1
.NOTES
    None
#>            
Write-Host "Hello World"


The second "gotcha" is around the fact that Get-Help says that "at the end of the script file" is a valid location for Comment-based Help for a script. This is true, but if you do this, be aware of the fact that if you subsequently sign your script, a signature block is added to the end of the script which means that your Comment-Based Help block is no longer at the end of the file, and you will get the symptom described above.

Write-Host "Hello World"            
<#
.SYNOPSIS
    Tests whether PowerShell 2 Comment-based Help is working as expected
.DESCRIPTION
    Displays Comment-based Help for this script
.EXAMPLE
    Test-CommentBasedHelp.ps1
.NOTES
    None
#>            

# SIG # Begin signature block            
# MIID/wYJKddoZIhvcNAQcCoIID8DCCA+wCAQExCzAJBgUrDgMCGgUAMGkGCisGAQ            
# gjcWqCA56QSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYp            
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUXPsShpFvys7oIWj23R6GpiQb            
# l46gggIdMIICGTCCAYKgAwIBAgIQSqeTRu71Hp1OJu+xx6ASfzANBgkqhkiG9w0B            
# AQQFADAYMRYwFAYDVQQDEw1OaWdlbCBCd5b3VsdG9uMCAXDTAwMDEwMTAwMDAwMF            
# DzIwOTkwMTAxMDAwMDAwWjAYMRYwFA68YDVQQDEw1OaWdlbCBCb3VsdG9uMIGfMA            
# CSqGSIb3DQEBAQPd789yhiCBiQKBgQC0+WAMn64J4oKsTIKsbBH5cTB4fEnfafzG            
# 1G+QkkgHpimfbT0Y+XrfmqKP6G/ailX3BHvwYOMmuSARqutfF6Rv9AQ7B/Sl8BgH            
# +AztcWg+jNko9dTidqexjH+bunpbzFMIJ6Lnzr+xSBvAbQR8oWtOwodQASW0G4Ra            
# b7+u5VZBaQIDAQABo2IwYDATBgNVHSUEDDAKBggrBgEFBQcDAzBJBgNVHQEEQjBA            
# gBCJKelkj8xj96uouh6cXclzoRowGDEWMBQGA1UEAxMNTmlnZWwgQm91bHRvboIQ            
# SqeTRu71Hp1OJu+xx6ASfzAHJy578}iG9w0BAQQFAAOBgQBw/WwbWGAHyyGjDhpb            
# Z7i8duiLHBBRYfUpczIh02jXPU+DfWa7atfwuFyxeilUDTszZ/2dOplH8l394j3H            
# yy8ZqXTf796zLqWXmvZn85rkgm16rRXqzDBheHidyTP3cPRPn7ehCahAAqpmHS0y            
# H7X3bevXIvMwDSXpL47nCCfWUDGCAUwwggFIAgEBMCwwGDEWMBQv0GA1UEAxMNTm            
# ZWwgQm91bHRvbgIQSqeTRu71Hp1OJu+xx6ASfzAJBgUrDgMCGgUAoHgwGAYKKwYB            
# BAGCNwIBDDEKMAhjY7guigAoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNw            
# BgorBgEEAYI3ACBgELMQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQULr            
# hd1Ib4bCuTXkm35KwTLDIiK58wDQYJKoZIcxhvcNAQEBBQAEgYCPumseo6AGAZFD            
# R37Tj8Kx6E0E6+MHqMHZ1TcLjO3E/lZqzFW7cCTJOcIH6Yg78r2DiToGXISdJkk8            
# 9sBB3nbsvQHWsWOYdRVwH8VueRg9paSa3CMj87E500z6bElejYGOi9VVfDZ8xBwm            
# rY4aAWd5A2dDpnojJQLC1yCv8w==            
# SIG # End signature block

Update: Please see the comment below from June Blender at Microsoft, who writes PowerShell Help. She has kindly updated the PowerShell Online Help topic about_Comment_Based_Help (available here) to reflect this "gotcha". Some further good news is that this change made it into the Windows PowerShell 2.0 Core Help May 2011 Update, which provides updated PowerShell Help in a CHM format (handy for searching!).

Hope this information is useful to you, I spent more time than I would have liked chasing this around!

Comments (25) Trackbacks (0)
  1. I agree – that first gotcha is a bit tricky when you’re reading the docs. It’s definitely all in the documentation, but I can see how easy it would be to miss. It’s also something I never knew and would probably drive me nuts when I eventually run into it.

    The solution to the second gotcha is to not sign your code 🙂

    Good article.

    Thanks,
    Tome

  2. Excellent article! I wrote the about_Comment_Based_Help file and I’ll be happy to amend it.

    The “blank line” requirement is in the second paragraph of the script syntax section. I can highlight it, but I don’t see a better place for it. I state the general syntax rule and then explain this requirement. I’m definitely open to suggestions, so please send them to me.

    The signing issue is more serious. Please file a bug on http://connect.microsoft.com/powershell and send me the bug #.

    ** Special thanks to Aleksandar Nikolic for sending me a link to this blog post. If you find any doc issues in the future, please be sure to file them on Connect and send me a link.

    Thanks,
    June Blender [MSFT]

    • Many thanks for your comment June.

      You’re absolutely right about the layout of the Help for Comment-based Help, and it makes perfect sense. I think the problem in my case is that I tend to scroll quickly down to the section that I’m looking for (in this case the section “SYNTAX FOR COMMENT-BASED HELP IN SCRIPTS”) and not read the rest as thoroughly as I should – until I can’t work out why it’s not working that is! I expect many others share this downfall, especially when in a hurry to get a script working.

      The only suggestions that come to mind for this particular issue are as follows, but you may feel that they are too cumbersome:

      “SYNTAX FOR COMMENT-BASED HELP IN SCRIPTS

      Comment-based Help for a script can appear in one of the following two
      locations in the script, and is subject to the general conditions noted above
      under SYNTAX FOR COMMENT-BASED HELP.”

      Or

      “SYNTAX FOR COMMENT-BASED HELP IN SCRIPTS

      Comment-based Help for a script can appear in one of the following two
      locations in the script.

      — At the beginning of the script file. Script Help can be preceded in the
      script only by comments and blank lines. If a Script Help topic follows
      a comment that is not part of the Help topic, there must be at least one
      blank line between the last non-Help comment line and the beginning of
      the Script Help.”

      I have filed a bug report for the signing issue as requested, the bug number is 667493.

      May I take this opportunity to say that I think the Help in PowerShell is some of the best that Microsoft have produced over the years. I never cease to be impressed that key people in the PowerShell Team at Microsoft participate so actively in the community, take the time to interact with end users such as myself, and are always ready to take on board our feedback.

  3. You can find my bug report for the signing issue on Microsoft Connect here. Please feel free to vote it up!

  4. Also I note that not all of the comment-based help “.*” tags seem to work. When I had .INPUT, .OUTPUT, and .PARAMETER entries get-help failed silently. I am trying to narrow down which ones seemed to cause the problems.

  5. Thanks for the nice comments about PowerShell help. It’s really a community effort, so I appreciate everyone’s participation.

    On 5/09, I updated the topic to explain that you can place comment-based help at the end of the script, but if the script is signed, you should place it at the beginning.

    You’ll be pleased to know that while we were working on this, it was known in our little group as “Nigel’s update.” Thanks again for your help.

    • Thanks June, that’s great. I’m sure it will save a lot of people some trouble as they may not re-test Script Help after signing their script.

      All – for reference, the updated topic is available here.

  6. Malcolm, if you can repro that error, ij me and I’ll have a look at it.

  7. This is quite late, but its helpful nonetheless for those that come after…
    If you have a mispelled, or invalid keyword in the definition you get nothin. This took me quite a while to figure out…

    Example below. Returnvalue keyword was specified from an example I found on the net. Its not actually a keyword according to documentation. It would be nice if there was some kind of error, or better yet it would just print out the keyword allowing you to create your own sections…

    .SYNOPSIS
    function synposis
    .DESCRIPTION
    function definition
    .NOTES
    File Name : SendDb.ps1
    Author : Seth Gray – [email protected]
    .RETURNVALUE
    returns a value…

    Removing returnvalue allows this to work properly

    • I think only .NOTES was conceived for extra stuff.

      btw. You can use .OUTPUTS to specify your output e.g.

      .OUTPUTS
      System.String Returns a value which is…

  8. Starting any line with a period that is not a valid tag seems to break help. A bummer if you want:

    .Example
    .Net 4.0 is a requirement for using this code.

    I end up having to either use ‘dot’ or ‘period’ to get around that.
    dot Net 4.0 ….

  9. Glad I stumbled upon this blog and read the comments.
    Had been all over TechNet, MSDN, forums, etc. ready about the placement of help comments in PowerShell scripts in relation to Function blocks etc. but only this from Seth Gray finally helped: “If you have a mispelled, or invalid keyword in the definition you get nothin.” Made me take a second look and realize I had been trying to define one of the “auto-generated” Keywords.

  10. Adding region support can break help also.

    Doing this breaks help:

    #region help text

    #endregion

    Must be:

    #region help text

    #endregion

  11. I’ve tried for an hour to get help working. I always get Get-Help : Get-Help could not find .\ChangeServiceCredentials.ps1 in a help file in this session. To download updated
    help topics type: “Update-Help”. To get help online, search for the help topic in the TechNet library at
    http://go.microsoft.com/fwlink/?LinkID=107116.
    At line:1 char:1
    + Get-Help .\ChangeServiceCredentials.ps1

  12. I get the exact same symptom.

    Below is a copy of what I wrote. The result comes up as
    Get-RebootHistory.ps1 [-computername] [[-entries] ] []

    The script works, but the help file doesnt display like expected. I followed the example like you did Nigel but not quite sure whats wrong.

    <

    [CmdletBinding()]
    param(
    [Parameter(Mandatory=$True)]
    [string] $computername,
    [string] $entries = '10'
    )
    Get-EventLog system -ComputerName $computername|Where-Object {$_.EventID -eq 1074}|select -First $entries

    • You have an errant ‘<' in your code above, Wei-Yen (but that could just be WordPress weirdness). Without that, it works as expected for me. If you add a comment block above the code, the help in it should be displayed when you run Get-Help .\Get-RebootHistory.ps1.

      • I have modified the actual programming slightly but the help part of is appearing with this output:

        Get-RebootHistory.ps1 [-computername] [[-entries] ] [[-path] ] []
        ________________________
        The full code is below.
        _____

        [CmdletBinding()]
        param(
        [Parameter(Mandatory=$True)]
        [string] $computername,
        [string] $entries = ’10’,
        [string] $path
        )
        Get-EventLog system -ComputerName $computername|Where-Object {$_.EventID -eq 1074}|select -First $entries | out-file $path -Width 400

  13. is there a kind of compiler / strict option / analyzer that would warn us automatically about ill-formatted comments, I have been staring at my code for 1/4h and still cannot find the reason why my help comments are not taken into account – waste of time! 🙁

    • Not that I know of Pierre. You could paste the code into something like Notepad++ and use ‘Show Symbol’ to see if there are any hidden characters that might be causing problems, or failing that try cutting half of the text to another file and seeing if that fixes it. If so, add back half of the text that you cut, and so on to narrow it down to a specific line (or lines). Good luck!


Leave a comment

No trackbacks yet.