Hey, Scripting Guy! How Do I Add Help Information for Windows PowerShell Parameters?

Bookmark and Share

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have been reading your articles this week about adding Help to scripts, and it looks really cool, but it also seems to be quite a bit of work. I would love to be able to display Help for a script when the script is run with a specific switch, but then it requires testing for the switched parameter and using nested if/then/else constructions. Is there an easier way to add Help information for parameters used in a Windows PowerShell script?

-- AW

Hey, Scripting Guy! Answer Hello AW,

Microsoft Scripting Guy Ed Wilson here. Well, it has finally happened. I recently got my annual ear infection. The bad thing is I am listening to the Meat Loaf CD the Scripting Wife placed in my stocking, and it sounds a little lopsided because I’m just about deaf in my right ear. As far as I can tell, the CD is awesome. The saving grace is that my Zune speakers are on my left side, so I can at least hear out of my good ear. The horrible thing is that the ear infection started during the holidays and I was not able to get out into my scripting wood working shop because the Scripting Wife would not let me out of the house. At times she has much more common sense than I do.

AW, listening to lopsided music is sort of like your approach to adding Help to your script. This is because you are focusing on only one avenue for adding Help. In Windows PowerShell 1.0, there was only one way to add Help, and that involved adding a switched parameter and typing various here-strings. In Windows PowerShell 2.0, you can integrate with the Windows PowerShell Help system by using the Get-Help cmdlet. To do this, you will need to use various stylized Help function tags.

Note: Portions of today's Hey, Scripting Guy! post are excerpted from the Microsoft Press book, Windows PowerShell 2.0 Best Practices by Ed Wilson, which is now available.

Much of the intensive work of producing Help information for your functions is removed when you use the stylized Help function tags that are available in Windows PowerShell 2.0. To use the Help function tags, you place the tags inside the block comment tags when you are writing your script. When you write Help for your function and employ the Help tags, it allows for complete integration with the Get-Help cmdlet. This provides a seamless user experience for those utilizing your functions. In addition, it promotes the custom user-defined function to the same status within Windows PowerShell as native cmdlets. The experience of using a custom user-defined function is no different than using a cmdlet, and indeed to the user there is no need to distinguish between a custom function that was dot sourced, loaded via a module, or a native cmdlet. The Help function tags and their associated meanings are shown in Table 1.

Table 1 Function Help Tags and Meanings

Help tag name

Help tag description


A very brief description of the function. It begins with a verb and tells the user what the function does. It does not include the function name or how the function works. The function synopsis appears in the SYNOPSIS field of all help views.


Two or three full sentences that briefly list everything that the function can do. The description begins with "The <function name> function…." If the function can get multiple objects or take multiple inputs, use plural nouns in the description. The description appears in the DESCRIPTION field of all Help views.


Brief and thorough. Describe what the function does when the parameter is used. And what legal values are for the parameter. The parameter appears in the PARAMETERS field only in Detailed and Full Help views.


Illustrate use of function with all its parameters. First example is simplest with only the required parameters. Last example is most complex and should incorporate pipelining if appropriate. The example appears only in the EXAMPLES field in the Example, Detailed, and Full Help views.


Lists the .NET Framework classes of objects the function will accept as input. There is no limit to the number of input classes you may list. The inputs Help tag appears only in the INPUTS field in the Full Help view.


Lists the .NET Framework classes of objects the function will emit as output. There is no limit to the number of output classes you may list. The outputs Help tag appears in the OUTPUTS field only in the Full Help view.


Provides a place to list information that does not fit easily into the other sections. This can be special requirements required by the function, as well as author, title, version, and other information. The notes Help tag appear in the NOTES field only in the Full help view.


Provides links to other Help topics and Internet Web sites of interest. Because these links appear in a command window, they are not direct links. There is no limit to the number of links you may provide. The links appear in the RELATED LINKS field in all Help views.


You do not need to supply values for all of the Help tags. As a best practice, however, you should consider supplying the .Synopsis and the .Example tag because these two tags supply the most critical information required to assist a person in learning how to use the function.

An example of using the Help tags is seen in the GetWmiClassesFunction1.ps1 script. First you will notice that there is no need to create a switched $help parameter. The reason for not needing the switched $help parameter is the incorporation of the code with the Get-Help cmdlet. When you do not need to use a switched $help parameter, you also do not need to test for the existence of the $help variable. By avoiding the testing for the $help variable, your script can be much simpler. You gain several other bonuses by using the special Help tags:

·         The name of the function is automatically displayed in all Help views.

·         The syntax of the function is automatically derived from the parameters and displayed in all Help views.

·         Detailed parameter information is automatically generated when the –full parameter of the Get-Help cmdlet is used.

·         Common parameter information is automatically displayed when Get-Help is used with the –detailed and –full parameters

In the GetWmiClassesFunction1.ps1 script, the Get-WmiClasses function begins the Help section with the Windows PowerShell 2.0 multiline comment block. The multiline comment block special characters begin with the left angle bracket followed with a pound sign (<#) and end with the pound sign followed by the right angle bracket (#>). Everything between the multiline comment characters is considered to be commented out. Two special Help tags are included: .Synopsis and .Example. The other Help tags that were listed in Table 1 are not used for this function.

      Displays a list of WMI Classes based upon a search criteria
     Get-WmiClasses -class disk -ns rootcimv2"
     This command finds wmi classes that contain the word disk. The
     classes returned are from the rootcimv2 namespace.

After the GetWmiClassesFunction.ps1 script is dot-sourced into the Windows PowerShell console, you can use the Get-Help cmdlet to get Help information from the Get-WmiClasses function. This is seen in the following image.

Image of getting Help from Get-WmiClasses function


Because the Help tags integrate with the Windows PowerShell help subsystem, you can use the various parameters from the Get-Help cmdlet to modify the Help output. As seen in the following image, you can display only the examples.

Image showing you can only dislay examples


The complete GetWmiClassesFunction1.ps1 script is seen here.


Function Get-WmiClasses(
      Displays a list of WMI Classes based upon a search criteria
     Get-WmiClasses -class disk -ns rootcimv2"
     This command finds wmi classes that contain the word disk. The
     classes returned are from the rootcimv2 namespace.
      throw "USAGE: getwmi2 -class <class type> -ns <wmi namespace>"
    } #$local:paramMissing
  "`nClasses in $ns namespace ...."
  Get-WmiObject -namespace $ns -list |
  where-object {
                 $_.name -match $class -and `
                 $_.name -notlike 'cim*'
  # mred function
} #end get-wmiclasses


AW, that is all there is to using Help tags. This also concludes Windows PowerShell Help Week. Tomorrow, we will open the mail bag and pull out some questions that require short answers. Yep, Quick-Hits Friday!

If you want to know exactly what we will be covering tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.


Ed Wilson and Craig Liebendorfer, Scripting Guys


Comments (11)

  1. Anonymous says:

    Hi scrpting guys! ^^
    i came across more complex scenario and i’m looking for nested parametrs – build parameter dependency. i was not able to find a way to create such structure ):

    i have a multipurpose script to handle different type of objects – i.e. users, computers, printers. then for each object i have a map of option – some non-obligatory switches, but then some mandatory option IF switches are present.

    script [-userobject [[-list filename] [-check] ] [-create filename] [-username username]] [-computerobject [[-list filename] [-check]] ….

    so what is interesting is dependency between check, list and userobject. this of course might be forced by some validation functions but i wonder if this is possible to be done with parameter options only…


  2. Anonymous says:

    @Trix – High five!

  3. Josh says:

    I am trying to get help with my first scripting assignment for school and have no idea where to start so if anybody could help me I would appreciate it. Here is the assignment:

    Create a Script named YourName-ManageUsers.ps1 that performs the following functions

    1. Allow user to input a filename to process.

    a. Allow the filename to be entered at the command line (as a parameter to the script)

    b. If no filename is specified allow the user to enter or select the file to process (your choice)

    2. Read the xml file and perform the following tasks.

    3. Create the users.   The users are listed in the <userManagement> node of the xml file. The <userManagement> node will have an arbitrary number of <user> nodes that contain user information.

    a. Create the user account in the organizational unit defined by the <ou> data.  Create the OU (off the domain root) if it does not exist.

    b. Set the users name to the value in <account>

    c. Set the other information as listed

    d. Make sure each account is not disabled

    e. Require the user to change their password next time they log in

    f. Add the user to the domain security groups listed in the <memberOf> node.  If the group does not exists create it.

    4. Process the items in the <localgroupManagement> node.

    a. Find all non-domain controller computers in the domain

    b. Add the domain global group specified in the <members><group> node(s) to each discovered computer’s local group specified by the <name> node.  If the local group does not exist create it.

    Provide output as appropriate as the script executes.

  4. WTFdoIknow...Imjustanengineer says:

    I have a problem with a Powershell script I'm using, but I can't find a place to post a new question. Can I post here?

  5. DheerajtheDJ says:

    Great start point ED.

    Had one question though that in case I wish to put in more than one examples then should I go about creating multiple example tags?

  6. Tim says:

    I could use your help I am stuck on an activity and am drawing a blank on how to do it. Here is the activity:
    This script should do the following:
    Create a new Windows log called Activity13_1 and assign a provider
    Create a new file named “c:tempmytarget.txt”
    Add a few lines of text to it
    Assign the value “NO” to a variable called $trigger
    Assign an empty string to a variable called $old_len
    Assign an empty string to a variable called $old_writetime
    Create a while loop that will loop until $trigger is equal to “YES”
    Write a log entry stating that your script is starting up
    Inside of the loop:
    Check to see if the file exists; if it does not, write a log entry to your new log stating that the script is terminating with error, set $trigger equal to “YES”, and then continue the loop
    Get file information for your file using Get-ChildItem
    If $old_len and $old_writetime are empty strings, set your variables equal to the Lengh and LastWriteTime properties from your object and then continue the loop
    Assign the Length of your object to a new variable called $curr_len
    Assign the LastWriteTime of your object to a new variable called $curr_writetime
    Compare the old and current variables:
    If both sets of variables are equal, then sleep the script for 5 seconds and then continue the loop
    If the length variables are different, write a log entry describing your findings, sleep the script for 3 seconds and then continue the loop
    If the writetime variables are different, write a log entry describing your findings, sleep the script for 3 seconds and then continue the loop

    And this is what I have so far:

    New-EventLog -LogName Activity13_1 -Source C:tempmyerrorresults.txt
    New-Item C:Tempmytarget.txt
    Add-Content C:Tempmytarget.txt ” I think I could on to this finally”
    Add-Content C:Tempmytarget.txt “Hopefully DocV will be shocked”
    Add-Content C:Tempmytarget.txt ” I know I am”
    $trigger = $false
    $old_len = ”
    $old_writetime = ”

    Add-Content c:tempmytarget.txt ” THE SCRIPT IS STARTING UP “

    while (“$trigger = $false”)
    Continue until $trigger = $true

    Test-Path c:tempmytarget.txt

    $trigger = “C:Tempmytarget.txt”

    $FileExists = Test-Path $trigger

    if($FileExists -eq “$false”) {Break}

    Add-Content C:Tempmytarget.txt “Terminating with error”

    if( $trigger = $true) {Continue}


    Get-ChildItem c:tempmytarget.txt

    if ($old_len -eq 0) {Get-ChildItem c:tempmytarget.txt | Measure-Object -Property length -Sum}

    if ($old_writetime -eq 0) {Get-ChildItem c:tempmytarget.txt | Measure-Object -Property LastWrite Time -Sum}

    Any help is appreciated.

  7. Jeff25 says:

    I know nothing about Powershell, but want to learn. My company is doing a computer upgrade in all cubicles. I have to "clean up" Active Directory by deleting the old computer names from AD. Before deleting the old names, I must copy the cubicle location
    (description attribute) and paste it in the description attribute of the new computer that replaced the old computer (hope this is making sense). It’s brutally boring. I was thinking there’s got to be a way to automate this, but don’t have a clue. Help!

  8. Trix says:

    Dear people who write the words "scripting assignment" – no-one wants to do your homework for you.

  9. Woter says:

    Hi Ed, Craig,

    First question to you – an avid reader and a none-do my homework question.

    I’m using the param block rather than specifying the parameters in the function name, however I can’t see why the $paramMissing variable doesn’t work:

    function find-applicationbyuser

    throw "When specifying type of ‘user’ the full username must be entered"

    It continues past the "throw" regardless of the $fullusername parameter -ne $null or -eq $null.

    Any ideas or suggestions?



  10. Pierre says:

    I came here to know how to format the .PARAMETER
    I would have liked a comrehensive example…

  11. Christian says:

    Hello Everyone,

    When I tried to build a help block I stumbled upon a strange phenomenon. I started the .OUPUTS information with ".", the DOT. apparently this is a no no since this results in not showing ANY help information. Is this a known issue / feature? If I try to "escape"
    the dot character for example with "“" the help information is shown but then including the escape character.

    to illustrate:

    shows information

    blah blah

    .csv File that blah blah

    results in NO information when using get-help

Skip to main content