{"id":8804,"date":"2015-02-18T06:00:00","date_gmt":"2015-02-18T14:00:00","guid":{"rendered":"http:\/\/www.sapien.com\/blog\/?p=8804"},"modified":"2016-04-25T07:41:06","modified_gmt":"2016-04-25T14:41:06","slug":"troubleshooting-comment-based-help","status":"publish","type":"post","link":"https:\/\/dev.sapien.com\/blog\/2015\/02\/18\/troubleshooting-comment-based-help\/","title":{"rendered":"Troubleshooting Comment-Based Help"},"content":{"rendered":"<p><a class=\"twitter-follow-button\" href=\"https:\/\/twitter.com\/juneb_get_help\" data-lang=\"en\">Follow @juneb_get_help<\/a><\/p>\n<p>A Windows PowerShell user group member recently came to me with a question about comment-based help in Windows PowerShell. It reminded me again that comment-based help is not as easy to use as you might think. Here are a few tips to help you avoid and fix obvious pitfalls.<\/p>\n<p>TIP: When testing help, be sure to restart your session between each test. Windows PowerShell caches help for the session, so changes to the help are effective only in a new session.<\/p>\n<p>&nbsp;<\/p>\n<p><a href=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image22.png\"><img loading=\"lazy\" decoding=\"async\" style=\"display: inline; border-width: 0px;\" title=\"image\" src=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image_thumb13.png\" alt=\"image\" width=\"493\" height=\"277\" border=\"0\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>RTFM: about_Comment_Based_Help<\/h2>\n<p>The best way to avoid errors is to read the <a href=\"http:\/\/go.microsoft.com\/fwlink\/?LinkID=144309\" target=\"_blank\">about_Comment_Based_Help<\/a> topic. It covers issues like the placement of comment-based help in functions, scripts, and script modules. It lists the keywords and provides some useful examples. Be sure to start there. This post is supplemental.<\/p>\n<p>&nbsp;<\/p>\n<h2>Use Only Valid Keywords<\/h2>\n<p>Comment-based help must include only valid keywords. If even one keyword is invalid, Get-Help ignores the entire comment-based help block and displays auto-generated help.<\/p>\n<p>The keyword names are case-insensitive, but they must be spelled exactly as specified. The dot and the keyword name cannot be separated by even one space. None of the keywords are required* in comment-based help, but you can&#8217;t add or change keywords, even it you really want a new one (such as .FILENAME, which would be a really good idea). If you use .NOTE (instead of .NOTES) or .EXAMPLES (instead of .EXAMPLE), Get-Help doesn&#8217;t display any of it.<\/p>\n<p>It&#8217;s very picky! If the format of a keyword is wrong, such as forgetting to place the parameter name on the same line as the .PARAMETER keyword, the entire comment-based help block is ignored.<\/p>\n<pre lang=\"PowerShell\">.SYNOPSIS\r\n.DESCRIPTION\r\n.PARAMETER\r\n.EXAMPLE\r\n.INPUTS\r\n.OUTPUTS\r\n.NOTES\r\n.LINK\r\n.COMPONENT\r\n.ROLE\r\n.FUNCTIONALITY\r\n.FORWARDHELPTARGETNAME\r\n.FORWARDHELPCATEGORY\r\n.REMOTEHELPRUNSPACE\r\n.EXTERNALHELP<\/pre>\n<p>*.ExternalHelp is required for function with Help XML files, but it&#8217;s not required for the comment-based help display.<\/p>\n<p>Also, for function help placed immediately before the function, you can have no more than one line blank line between the end the help block and the line on which the function is defined. If there are two blank lines, Get-Help associates the help with the script or module file, not the function.<\/p>\n<p>This is valid function help.<\/p>\n<pre lang=\"PowerShell\">\r\n<#\r\n .DESCRIPTION\r\n Nice function\r\n#>\r\nfunction Get-NiceFunction {}<\/pre>\n<p>This is valid function help.<\/p>\n<pre lang=\"PowerShell\">\r\n<#\r\n .DESCRIPTION\r\n Nice function\r\n\r\n#>\r\nfunction Get-NiceFunction {}<\/pre>\n<p>This doesn&#8217;t work. Get-Help displays auto-generated help for the function. It associates the help comments with the script, not the function.<\/p>\n<pre lang=\"PowerShell\">\r\n<#\r\n .DESCRIPTION\r\n Nice function\r\n#>\r\n\r\n\r\nfunction Get-NiceFunction {}<\/pre>\n<p>&nbsp;<\/p>\n<h2>Distinguish HelpMessage from Parameter Comments and .PARAMETER<\/h2>\n<p>There are three ways to add a parameter description to function help. I&#8217;ve listed them below in precedence order.<\/p>\n<p>Notice that Get-Help displays a <strong>parameter comment<\/strong> only when there is at least one valid comment-based help keyword for the command and it is not a .PARAMETER keyword for the same parameter. If the parameter comment is the only help for the command, it is ignored.<\/p>\n<p>Also, the HelpMessage attribute is part of auto-generated help, not comment-based help.<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li><strong>The .PARAMETER keyword<\/strong> takes precedence over other parameter description types.\u00a0Get-Help\u00a0displays\u00a0it\u00a0even when it is the only comment-based help keyword for the function.<\/li>\n<\/ul>\n<pre lang=\"PowerShell\">&lt;#\r\n    .PARAMETER Name\r\n     Enter a unique name for the widget.\r\n#&gt;\r\n<\/pre>\n<ul>\n<li><strong>A parameter comment<\/strong> appears in the Get-Help display\u00a0when there is valid comment-based help, but no .PARAMETER keyword for that parameter.<\/li>\n<\/ul>\n<pre lang=\"PowerShell\">Param\r\n(\r\n    [Parameter(Mandatory = $true)]\r\n    [string]\r\n    # Enter a unique name for the widget.\r\n    $Name\r\n)<\/pre>\n<ul>\n<li><strong>The HelpMessage attribute<\/strong> appears in the Get-Help -Full and -ShowWindow display only when there is no help of any type for the command.<\/li>\n<\/ul>\n<pre lang=\"PowerShell\">Param\r\n(\r\n    [Parameter(Mandatory = $true, HelpMessage = \"Enter a unique name for the widget.\")]\r\n    [string]\r\n    $Name\r\n)<\/pre>\n<p>&nbsp;<\/p>\n<p>According to the <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/system.management.automation.parameterattribute.helpmessage(v=vs.85).aspx\" target=\"_blank\">MSDN docs<\/a>, the <strong>HelpMessage<\/strong> attribute of a parameter appears when Windows PowerShell prompts for a mandatory parameter value, but Get-Help doesn&#8217;t display it. Based on my tests of Windows PowerShell 2.0 \u2013 5.0 preview, Get-Help does display the HelpMessage attribute value in auto-generated help.<\/p>\n<p>The HelpMessage attribute appears when you type <strong>!?<\/strong> in response to a mandatory parameter prompt.<\/p>\n<pre lang=\"PowerShell\">function Get-CBHelp\r\n{\r\n    param\r\n    (\r\n        [Parameter(Mandatory = $true, \r\n                   HelpMessage = \"Enter a unique name for the widget.\")]\r\n        [String]\r\n        $Name\r\n    )\r\n    $Name\r\n}<\/pre>\n<pre class=\"output\">PS C:\\&gt; . .\\Test-CBHelp.ps1\"\r\nPS C:\\&gt; Get-CBHelp\r\ncmdlet Get-CBHelp at command pipeline position 1\r\nSupply values for the following parameters:\r\n(Type !? for Help.)\r\nName: !?\r\nEnter a unique name for the widget.\r\n<\/pre>\n<p>However, it also appears in auto-generated help with\u00a0-Full or -ShowWindow\u00a0when there is no help for the command. To make Get-Help ignore the comment-based help and display auto-generated help, I&#8217;ll just delete the first &#8220;S&#8221; from .SYNOPSIS.<\/p>\n<pre lang=\"PowerShell\">&lt;# .YNOPSIS \r\n    Tests elements of comment-based help \r\n.DESCRIPTION \r\n    This function doesn't do anything. It was created only for testing. \r\n.PARAMETER Name \r\n    This is the parameter keyword. \r\n.EXAMPLE \r\n    PS C:\\&gt; Get-CBHelp -Name Plebius\r\n    Plebius\r\n#&gt;\r\nfunction Get-CBHelp\r\n{\r\n    Param\r\n    (\r\n        [Parameter(Mandatory = $true, HelpMessage = \"This is the HelpMessage attribute.\")]\r\n        # Here is the parameter comment.\r\n        [string]\r\n        $Name\r\n    )\r\n    $Name\r\n}\r\n<\/pre>\n<p>&nbsp;<\/p>\n<pre class=\"output\">PS C:\\&gt; . .\\Test-CBHelp.ps1\r\nPS C:\\&gt; Get-Help -Full Get-CBHelp\r\n\r\nNAME\r\nGet-CBHelp\r\n\r\nSYNTAX\r\nGet-CBHelp [-Name] &lt;string&gt;\u00a0 [&lt;CommonParameters&gt;]\r\n\r\nPARAMETERS\r\n-Name &lt;string&gt;\r\nThis is the HelpMessage attribute.\r\n\r\nRequired?\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 true\r\nPosition?\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0\r\nAccept pipeline input?\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 false\r\nParameter set name\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 (All)\r\nAliases\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 None\r\nDynamic?\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 false\r\n\r\n<\/pre>\n<p>&nbsp;<\/p>\n<h2>Use .ExternalHelp for Function Help XML Files<\/h2>\n<p>There are no required keywords in comment-based help. For example, if you have a comment-based help block that contains only a .INPUTS keyword and its value, Get-Help displays the Inputs section that you specify and fills in the rest from auto-generated help.<\/p>\n<p>The only keyword that might be thought of as required is .EXTERNALHELP. This comment keyword must appear when help for a function is written in a Help XML file. Unlike the help XML files for other command types, help XML files for functions do not have standard names or locations. Thus, without .EXTERNALHELP, Get-Help does not know where to look for an Help XML file, regardless of its name and location.<\/p>\n<p>The value of the .EXTERNALHELP keyword is the name of the help XML file without a path. Get-Help looks for a file with that name in a language-specific subdirectory of the module directory.<\/p>\n<p>For example, because of the value of the .EXTERNALHELP keyword, Get-Help knows that it should look for a help topic for my Update-OneGet function in the UpdateOneGet.psm1-help.xml file in the en-US (or de-DE, etc) directory of its module directory, ($home\\Documents\\WindowsPowerShell\\Modules\\UpdateOneGet\\en-US\\UpdateOneGet.psm1-help.xml).<\/p>\n<pre lang=\"PowerShell\"># .EXTERNALHELP UpdateOneGet.psm1-help.xml\r\nfunction Update-OneGet\r\n{\r\n    Param\r\n    ...\r\n(<\/pre>\n<p>For more information about writing XML help files for functions, see <a href=\"https:\/\/www.sapien.com\/blog\/2015\/04\/01\/writing-xml-help-for-advanced-functions\/\" \"target=_blank\">Writing XML Help for Advanced Functions<\/a>.<\/p>\n<p>For more information about naming help files so Get-Help can find them, see <a href=\"https:\/\/msdn.microsoft.com\/en-us\/library\/dn423135(v=vs.85).aspx\" target=\"_blank\">Naming Help Files<\/a>.<\/p>\n<h2>Precedence<\/h2>\n<p>Comment-based help takes precedence over XML help, so if you have both, Get-Help gets only the comment-based help. However, the .EXTERNALHELP comment keyword takes precedence over comment-based help. So, if you have both, Get-Help gets only XML help. <\/p>\n<p>For example, given the following comment-based help content, Get-Help displays the XML help in MyModule.psm1-help.xml and ignores the .LINK.<\/p>\n<pre lang=\"PowerShell\">\r\n<#\r\n.EXTERNALHELP MyModule.psm1-help.xml\r\n.LINK\r\nhttp:\/\/www.sapien.com\/blog\r\n#><\/pre>\n<p>&nbsp;<\/p>\n<h2>Use great tools<\/h2>\n<p>I need to mention that great PowerShell tools help you to avoid these syntactic problems.<\/p>\n<p>For example, in <a href=\"http:\/\/www.sapien.com\/software\/powershell_helpwriter\" target=\"_blank\">PowerShell Help Writer<\/a>, you write help topics in an environment customized for authoring Windows PowerShell help. You don&#8217;t need to worry about syntax or any other implementation details. You select a module and PowerShell Help Writer generates starter help topics with the correct syntax. If you have existing help, including comment-based help, it converts it automatically. This is really the ultimate help authoring environment.<\/p>\n<p><a href=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image23.png\"><img loading=\"lazy\" decoding=\"async\" style=\"display: inline; border-width: 0px;\" title=\"image\" src=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image_thumb14.png\" alt=\"image\" width=\"566\" height=\"395\" border=\"0\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>In <a href=\"http:\/\/www.sapien.com\/software\/powershell_studio\" target=\"_blank\">PowerShell Studio<\/a>, the Function Builder (Insert function\/Edit function) lets you compose comment-based help for a function while you&#8217;re writing the function. It adds the correct syntax so you don&#8217;t have to think about it.<\/p>\n<p><a href=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image24.png\"><img loading=\"lazy\" decoding=\"async\" style=\"display: inline; border-width: 0px;\" title=\"image\" src=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image_thumb15.png\" alt=\"image\" width=\"612\" height=\"427\" border=\"0\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>PowerShell Studio also generates comment-based help on demand.<\/p>\n<blockquote><p><a href=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image25.png\"><img loading=\"lazy\" decoding=\"async\" style=\"display: inline; border-width: 0px;\" title=\"image\" src=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image_thumb16.png\" alt=\"image\" width=\"364\" height=\"438\" border=\"0\" \/><\/a><\/p><\/blockquote>\n<p>And, when you&#8217;re editing comment-based help in PowerShell Studio, PrimalSense suggests and inserts keywords with the correct spelling and format.<\/p>\n<p><a href=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image26.png\"><img loading=\"lazy\" decoding=\"async\" style=\"display: inline; border-width: 0px;\" title=\"image\" src=\"http:\/\/www.sapien.com\/blog\/wp-content\/uploads\/2015\/02\/image_thumb17.png\" alt=\"image\" width=\"274\" height=\"344\" border=\"0\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Writing comment-based help seems a bit more complicated than it needs to be. But knowing the &#8220;gotchas&#8221; makes the task of writing valid comment-based help a bit easier.<\/p>\n<p>[Thanks to Windows PowerShell MVP <a href=\"http:\/\/mvp.microsoft.com\/en-us\/mvp\/aleksandar%20nikolic-4027175\" target=\"_blank\">Aleksandar Nikolic<\/a> for correcting the &#8220;!?&#8221; omission in the original post.]<\/p>\n<p><em>June Blender is a technology evangelist at SAPIEN Technologies, Inc. You can reach her at <\/em><a href=\"mailto:juneb@sapien.com\"><em>juneb@sapien.com<\/em><\/a><em> or follow her on Twitter at <\/em><a href=\"https:\/\/twitter.com\/juneb_get_help\"><em>@juneb_get_help<\/em><\/a><em>.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Follow @juneb_get_help A Windows PowerShell user group member recently came to me with a question about comment-based help in Windows PowerShell. It reminded me again that comment-based help is not as easy to use as you might think. Here are a few tips to help you avoid and fix obvious pitfalls. TIP: When testing help, [&hellip;]<\/p>\n","protected":false},"author":31,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[25],"tags":[934,28],"class_list":["post-8804","post","type-post","status-publish","format-standard","hentry","category-windows-powershell","tag-juneb","tag-powershell"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8804","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/users\/31"}],"replies":[{"embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/comments?post=8804"}],"version-history":[{"count":27,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8804\/revisions"}],"predecessor-version":[{"id":11858,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/posts\/8804\/revisions\/11858"}],"wp:attachment":[{"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/media?parent=8804"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/categories?post=8804"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dev.sapien.com\/blog\/wp-json\/wp\/v2\/tags?post=8804"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}