This one bit me, when trying to convert the inline help of a PowerShell cmdlet into some markdown enriched code for Github.
For the PowerShell modules and Cmdlet we publish at github we sometimes use the integrated Wiki pages from Github to have some documentation on their use. We often also extract the full inline help and paste it to the wiki page for the respective Cmdlet so people can have a look at it even when they do not have the modules installed. In general this works fine, but a small nuisance is, that the automatic formatting of sections (uppercase) has to be followed by an additional line break, which is not how PowerShell renders the inline help. So why not use PowerShell to help PowerShell with its formatting? A simple and-and-a-half-liner should suffice (which is actually wrapped for better readability), so I thought first:
PARAM ( $CommandName = 'ConvertTo-Json' ) $helpFormatted = @(); foreach($line in ((Get-Help $CommandName -Full))) { if( ![string]::IsNullOrWhiteSpace($line) -and $line -ceq $line.ToUpper() ) { $line = "{0}`r`n" -f $line; } # if $helpFormatted += $line; } # foreach return $helpFormatted;
However, this just brings us the following error message:
PS> $error[0].Exception Method invocation failed because [MamlCommandHelpInfo#Microsoft.PowerShell.Utility#ConvertTo-Json#FullView] doesn't contain a method named 'ToUpper'.
That was rather strange, because looping over this array must be possible:
PS > $help = help $CommandName -Full; PS > $help.GetType(); IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array
And why shouldn’t this work, as ‘help’ is an alias to ‘Get-Help’, right? At least calling ‘help’ on ‘help’ pretends that …
PS > help help | Select -First 7 NAME Get-Help SYNOPSIS Displays information about Windows PowerShell commands and concepts.
… but actually not really, as it turns out:
PS > $help = Get-Help $CommandName -Full; PS > $help.GetType(); IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True PSCustomObject System.Object
So depending on whether we call ‘help’ or ‘Get-Help’ either an array or a PSCustomObject is returned. What happened here? A closer look at the ‘Definition’ of the ‘help’ function reveals that it is more than just an alias, but instead a script that invokes ‘Get-Help’ and returns its output by piping it through ‘more’:
PS > (Get-Command help).Definition <# .FORWARDHELPTARGETNAME Get-Help .FORWARDHELPCATEGORY Cmdlet #> [CmdletBinding(DefaultParameterSetName='AllUsersView', HelpUri='http://go.microsoft.com/fwlink/?LinkID=113316')] param( [Parameter(Position=0, ValueFromPipelineByPropertyName=$true)] [string] ${Name}, [string] ${Path}, <# some parameters left out for better readability #> [Parameter(ParameterSetName='Online', Mandatory=$true)] [switch] ${Online}, [Parameter(ParameterSetName='ShowWindow', Mandatory=$true)] [switch] ${ShowWindow} ) #Set the outputencoding to Console::OutputEncoding. More.com doesn't work well with Unicode. $outputEncoding=[System.Console]::OutputEncoding Get-Help @PSBoundParameters | more
So, ‘mystery’ solved, but nevertheless strange, as I would expect to behave both ‘functions’ identically …
So coming back to our original problem we can either user ‘help’ or ‘Get-Help | more’ to markup the inline help:
PARAM ( $CommandName = 'ConvertTo-Json' ) $helpFormatted = @(); foreach($line in ((help $CommandName -Full))) { if( ![string]::IsNullOrWhiteSpace($line) -and $line -ceq $line.ToUpper() ) { $line = "{0}`r`n" -f $line; } # if $helpFormatted += $line; } # foreach return $helpFormatted; # You can then use 'Out-GridView' to display the results: # $helpFormatted | Out-GridView
See https://github.com/dfch/biz.dfch.PS.System.Utilities/blob/master/ConvertFrom-CmdletHelp.ps1 at biz.dfch.PS.System.Utilities for a full version of the Cmdlet.