Writing XML Help for Advanced Functions

April 1st, 2015 by June Blender
Last updated on September 2nd, 2015


The introduction of SAPIEN PowerShell HelpWriter has made writing XML help files as easy – actually easier – than writing comment-based help. XML help is more robust and less error-prone than comment-based help. It supports updatable help and help in multiple languages, and it lets you separate help files from script and modules files, which is a real advantage when you’re working with many people in a shared coding environment, like GitHub.

PowerShell HelpWriter makes it easy to create XML help files for all commands in a module, including the functions in a manifest module or script module: just click New/New Help File (from Module). But, you’re not quite done. It takes a few more steps to associate a function with the XML help file.


What do I name the XML Help file?

You need to give your XML help file a name that Get-Help expects. Otherwise, Get-Help won’t find your help file. Instead, it displays only auto-generated help.

In Windows PowerShell 3.0, the XML help files for cmdlets, providers, and CIM commands must be named for the file in which the commands are defined.

The name syntax is:


For example:


There are no requirements for the names of function help files, but, as a best practice, they are usually named for the .psm1 file in which they are defined plus “-help.xml”.

The best practice syntax is:


For example:


But, this best practice isn’t required. If your module includes cmdlets, providers, workflows, and/or CIM commands, along with functions, it’s sometimes easier to add the XML help topics for functions to the existing help file. For example, if you have a cmdlet/provider help file called MyModule.dll-help.xml, you can add your function help topics to that XML Help file.

For modules that run only in Windows PowerShell 4.0 and later, you can put XML files for all command types in one file that is named for the module. This technique is much easier for the help author to maintain, but Get-Help on Windows PowerShell 3.0 and earlier will not find help for commands in a module with this naming technique.

The name syntax is:


For example:


For information about naming Windows PowerShell help files, see Naming Help Files.


Where do I put the XML Help file?

Get-Help looks in for the XML Help file in the module directory and in language-specific subdirectories of the module directory. If it can’t find the XML Help file, Get-Help searches in subdirectories of the module directory, but this is a risky strategy that doesn’t work for all module types.

You have two options for placing an XML Help file:

  • In the module directory, that is, the value of the ModuleBase property of your module.For example, if the module directory of MyModule is:
    PS C:> (Get-Module MyModule –ListAvailable).ModuleBase

    you can place the XML help file for commands in my module here:

  • In a language-specific subdirectory of the module directory.This is the preferred location, because it lets you support help topics in multiple languages. Even if you have help in only one language today, a friend or colleague might translate your help for you in the future.For example, you can place the US English XML help files for commands in my module in the en-US subdirectory:


Special for functions: # .ExternalHelp

Get-Help doesn’t have any naming standards for XML help files for functions. Instead, to associate a function with the XML help file that contains its help topic, use the .ExternalHelp comment keyword (for details, see about_Comment_Based_Help).

The value of the .ExternalHelp comment keyword is the name of the help file that contains the help topic. Do not include any variables in the file name; they will be interpreted as literals. Also, do not specify a path. Get-Help looks for the help file in the module directory or language-specific subdirectory of the module directory.

For example, this comment line tells Get-Help that the help topic for MyFunction is in the MyModule.psm1-help.xml file.

# .ExternalHelp MyModule.psm1-help.xml
function MyFunction {...}

Be really careful here. The syntax is critical. If you have any syntax errors, Get-Help ignores the entire comment-based help block. For example, if the file name is on the line below the ExternalHelp keyword, the keyword is ignored.

In Windows PowerShell 4.0 and later, you can omit the .ExternalHelp comment keyword, but this works only for functions in manifest modules (not script modules) and only when the help file name is the name of the file in which the function is defined + “-help.xml”. To be safe (and backwards compatible), I add the .ExternalHelp comment keyword to every function that has an XML help file. The keyword also reminds me that the function has XML help so I don’t write comment-based help for it by mistake.

Precedence and XML Help

Just a quick word about precedence.

When a function has both comment-based help and an XML help file, Get-Help displays the comment-based help. But, if the comment-based help includes an ExternalHelp keyword, Get-Help ignores the comment-based help content and displays the XML help.

In fact, if the ExternalHelp keyword is present, Get-Help ignores the rest of comment-based help, even if it cannot find an XML help file that matches the value of the ExternalHelp keyword. Instead, it displays auto-generated help.

Also, if the comment-based help is invalid for any reason, like a typo in a comment keyword name, Get-Help ignores the comment-based help. For manifest modules, it gets XML help, if it exists, or displays auto-generated help. For script modules, it displays auto-generated help.

When writing a function, select comment-based help (x)or XML help. Including both is inviting errors. They’re bound to get out of sync and you’ll struggle to figure out why a new example isn’t displaying, only to find that you added the example to the format that isn’t being displayed.


Testing XML Help

To test an XML help file for a function, use Get-Help. When the module and the help are in the right place with the right name, Get-Help should find the help topic for the function even when the module is not imported into the session.

If you find an error, you can view the raw XML. A single function help topic consists of all content and elements within the <command:command> elements in the XML file.



To get the help topics in an XML help file, use the XML accelerator and the Get-Content cmdlet. For example, this command gets the help topics in Bitlocker.psm1-help.xml, the XML help file for the Bitlocker module.

[xml]$xml = Get-Content -Path $pshome\modules\Bitlocker\en-us\BitLocker.psm1-help.xml

To verify that a help topic is in the file, get the topic names. This command gets the names of topic in the Bitlocker.psm1-help.xml file.

PS C:\> $xml.HelpItems.command.Details.Name



You can also examine the XML help topic in the raw XML. This command gets the help topic for the Disable-Bitlocker function and saves it in the $disableBitlocker variable.

PS C:\> $disableBitlocker = $xml.helpItems.command | 
    where {$_.details.Name -eq "Disable-Bitlocker"}

Now, you can get the details, like the related links:

PS C:\ps-test> $disableBitlocker.relatedLinks.navigationLink

linkText                               uri
--------                               ---
Online Version:                        http://go.microsoft.com/fwlink/?linkid=287650

This command verifies that each function help topic has an online version link. It returns a custom object with the name and online version URI for each help topic.

PS C:\> $xml.helpItems.command | 
    Select-Object @{Label ="Name"; Expression ={$_.Details.Name}}, 
    @{Label="OnlineLink"; Expression={($_.relatedLinks.NavigationLink | 
    where LinkText -eq "Online Version:").uri}}

Name                                         OnlineLink
----                                         ----------
Add-BitLockerKeyProtector                    http://go.microsoft.com/fwlink/?linkid=287647
Backup-BitLockerKeyProtector                 http://go.microsoft.com/fwlink/?linkid=287648
Clear-BitLockerAutoUnlock                    http://go.microsoft.com/fwlink/?linkid=287649
Disable-BitLocker                            http://go.microsoft.com/fwlink/?linkid=287650
Disable-BitLockerAutoUnlock                  http://go.microsoft.com/fwlink/?linkid=287651
Enable-BitLocker                             http://go.microsoft.com/fwlink/?linkid=287652
Enable-BitLockerAutoUnlock                   http://go.microsoft.com/fwlink/?linkid=287653
Get-BitLockerVolume                          http://go.microsoft.com/fwlink/?linkid=287654
Lock-BitLocker                               http://go.microsoft.com/fwlink/?linkid=287655
Remove-BitLockerKeyProtector                 http://go.microsoft.com/fwlink/?linkid=287656
Resume-BitLocker                             http://go.microsoft.com/fwlink/?linkid=287657
Suspend-BitLocker                            http://go.microsoft.com/fwlink/?linkid=287658
Unlock-BitLocker                             http://go.microsoft.com/fwlink/?linkid=287659


I hope this helps. If you have a question about Windows PowerShell Help, post it in the Windows PowerShell forum or tweet it to me at @juneb_get_help. If you have a question about PowerShell HelpWriter, post it in the PowerShell HelpWriter forum or, for trial users, the Trial Software Questions forum.

June Blender is a technology evangelist at SAPIEN Technologies, Inc. You can reach her at juneb@sapien.com or follow her on Twitter at @juneb_get_help.


[Google+]   [Facebook]   [LinkedIn]   [StumbleUpon]   [Digg]   [Reddit]   [Google Bookmark]  

Tags: , ,