Monday, November 19, 2007

Help vs. Get-Help

Help text for any command-let in PowerShell can be viewed by executing "help cmdletName" or "get-help cmdletName". At first glance there's no difference between the two, both emits the relevant help to PowerShell's console, but under the cover they are completely different command types:

PS > (help get-command).gettype().fullname

PS > (get-help get-command).gettype().fullname


All members type of 'help get-command' are strings, while 'get-help get-command' returns rich PSCustomObject:


PS > (help get-command) | foreach {$_.gettype()}

IsPublic IsSerial Name                                    BaseType
-------- -------- ----                                         --------
True     True     String                                   System.Object
True     True     String                                   System.Object


PS > (get-help get-command) | foreach {$_.gettype()}

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                          --------
True     False    PSCustomObject                     System.Object


Now with Get-Member, which returns different type names:

PS > (help get-command) | gm
TypeName: System.String

PS > (get-help get-command) | gm
TypeName: MamlCommandHelpInfo


One might think (as I did) that "help" is a built-in alias for get-help:

PS > Get-Alias -name h* | format-table -auto

CommandType  Name     Definition
----------- ----    ------      ----
Alias                 h           Get-History
Alias                 history   Get-History

There is no such alias for get-help. Another test:

PS > get-alias | where {$_.Definition -match "Get-Help"}

No output. Typing help or get-help separately shows different output formats. Executing "Help" emits a list of PowerShell's built-in aliases, cmdlets, providers and about help files. It also supports paging (one screen at a time). On the other hand get-help outputs the help for the get-help cmdlet with no paging support.


So, what is "help"? Lets try get-command:

PS > get-command help  | ft -auto

CommandType   Name        Definition
----------- ----     -----          -----
Function             help         param([string]$Name,[string[]]$Category=@('All')...
Application         help.exe   C:\WINDOWS\system32\help.exe


Ah.. help is a function while get-help is a cmdlet. To view the source of the help function (edited):

PS > (dir function:\help).definition

if ($Detailed)
      #Detailed and #Full are in different sets..let get-help cmdlet handle the error
      get-help $Name -Full -Detailed  |

if ($Examples)
      #Examples and #Full are in different sets..let get-help cmdlet handle the error
      get-help $Name -Full -Examples  |


You can see that behind the scenes, the help function is kind of a proxy command. It pipes the typed help command and parameters to get-help and then pipes the result to to support paging.

Moreover, when you want to access certain member (like examples) to display a specific code example:

PS > (get-help get-command).examples.example[0]

-------------------------- EXAMPLE 1 --------------------------


This command retrieves information about all of the Windows PowerShell cmdlets....


Try the same with help and you'll get an error:

PS > (help get-command).examples.example[0]
Cannot index into a null array.
At line:1 char:37
+ (help get-command).examples.example[0 <<<< ]


So, if you need access to specific members of a certain cmdlet using the above examples use get-help. If you know other differences, please post them in the comments box.

1 comment:

Harkamal Singh said...


there's a nice link to generate html documentation for cmdlets by using output from Get-Help which spits rich object.

Script could then call and create html tags...

How ever if i create similar help text files as same format of Get-Help files. The format is String type not of MAML. So I cannot use CMDLET.Name
CMDLET.Synopsis type code to generate help for my script files.

Your article helped understand why. Is there a way around ?