Tag Archives: Help

Create an HTML PowerShell Help Page

Yesterday I posted an article about getting the online url for a cmdlet help topic. Today I want to demonstrate how we might take advantage of this piece of information.

Since the link is already in the form of a URL, wouldn’t it make sense to put this in an HTML document? At first glance, you might take the command from yesterday and pipe it to ConvertTo-HTML.


Get-Command -CommandType cmdlet | Get-Help |
Select Name,Synopsis,@{Name="URI";Expression={
($_.RelatedLinks | select -ExpandProperty NavigationLink | where {$_.uri}).uri}} |
Where {$_.URI} | ConvertTo-HTML -Title "Help Links" | Out-File c:\work\pshelp.htm

This code will work just fine. But if you look at the resulting file, we don’t have a link. I suppose it would be nice if ConvertTo-HTML could auto-detect URLs and automatically add a link, but it looks like we’ll have to do it. We could probably use a custom hash table to insert the HTML Anchor tags so here’s the first attempt:


Get-Command -CommandType cmdlet | Get-Help | Where {$_.RelatedLinks} |
Select Name,Synopsis,@{Name="URI";Expression={
#add the link tags as part of the output!
$link=$_.RelatedLinks | select -ExpandProperty NavigationLink | where {$_.uri}
if ($link.uri) {
$uri=$link.uri
Write "$uri"
}
else {
#no link so write a null
write $Null
}
}} | Where {$_.URI} | ConvertTo-HTML -Title "Help Links" |
Out-File c:\work\pshelp.htm

One additional change I made was to filter out cmdlets with no related links. Then in the expression scriptblock I can create a new value based on the URI value if it exists. But there is a problem with this, which you’ll see immediately if you run this code. ConvertTo-HTML sees the value of my new URI property and escapes the < and > characters.

That doesn’t help. But this is where the fact that ConvertTo-HTML only creates HTML code because we can parse the code and do a simple replace. Let me jump ahead and pull part of the finished dessert from the oven.


Function Convert-HTMLEscape {

<#
convert < and > to < and >
It is assumed that these will be in pairs
#>

[cmdletbinding()]

Param (
[Parameter(Position=0,ValueFromPipeline=$True)]
[string[]]$Text
)

Process {
foreach ($item in $text) {
if ($item -match "<") {
<#
replace codes with actual symbols
This line is a shortcut to do two replacements
with one line of code. The code in the first
set of parentheses revised text with "<". This
normally gets written to the pipeline. By wrapping
it in parentheses it tells PowerShell to treat it
as an object so I can then call the Replace()
method again and add the >.
#>
($item.Replace("<","<")).Replace(">",">")
}
else {
#otherwise just write the line to the pipeline
$item
}
}
} #close process

} #close function

This function takes string input, presumably from ConvertTo-HTML and replaces the HTML escapes with the “real” characters. This I can use to write to the file.


...| Where {$_.URI} | ConvertTo-HTML -Title "Help Links" | Convert-HTMLEscape | Out-File c:\work\pshelp.htm

One of the reasons I put this in a function is to make it re-usable for future projects where I might need to escape these characters again. We’re getting closer. One last thing before we ice the final dessert: I have been using an expression to get all cmdlet help. But I like flexibility. What if tomorrow I only want a page with New* cmdlets from PowerCLI? So once again, I took my code that works just fine from a prompt into a more flexible and re-usable function.

Function Get-HelpUri {

[cmdletbinding()]

Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a cmdlet name",
ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
[ValidateNotNullorEmpty()]
[string]$Name
)

Process {
Write-Verbose "Processing $name"
Get-Help $name | Where {$_.RelatedLinks} |
Select Name,Synopsis,@{Name="URI";Expression={
#add the link tags as part of the output!
$link=$_.RelatedLinks | select -ExpandProperty NavigationLink | where {$_.uri}
if ($link.uri) {
$uri=$link.uri
Write "$uri"
}
else {
#no link so write a null
write $Null
}
}}
} #close process

} #close function

This will write a custom object with the cmdlet name, synopsis and URI property with the HTML code. I still need to convert to HTML and then fix the tags but I can verify it works.


PS C:\> get-command new-object | get-helpuri | ConvertTo-Html |Convert-HTMLEscape
">

Name Synopsis URI
New-Object Creates an instance of a Microsoft .NET Framework or COM object. 'http://go.microsoft.com/fwlink/?LinkID=113355' target='_blank'>http://go.microsoft.com/fwlink/?LinkID=11335
5


The icing is to include some style via a CSS file. Here’s a short script on how I might build a file for all of the cmdlets in my current session.


Write-Host "Building cmdlet help report" -ForegroundColor Green

#the file to create
$file="c:\work\cmdletonline.htm"

#be sure to change the path to the CSS file if you want to use it
$cssPath="c:\scripts\blue.css"

#optional image
$imagePath="c:\work\talkbubble.gif"

#some pre content
$preContent=@"



Cmdlet Online Help




"@

#some post content
$postContent=@"

Help for cmdlets found on $env:computername on $(Get-Date)
"@

#a title for the report
$Title="Cmdlet Help"

<#
Get all cmdlets in the current session, send them to the Get-HelpURI
function to parse out help URLS, filter out those without a link, pass
the remaining to the Convertto-HTML to generate HTML code which is piped
to my function to replace < with > and the final HTML code is piped to
a file.
#>
Get-Command -CommandType cmdlet | Get-HelpURI | Where {$_.URI} |
ConvertTo-Html -PreContent $PreContent -PostContent $postContent -Title $Title -cssUri $cssPath |
Convert-HTMLEscape | Out-File -FilePath $file -Encoding ASCII

Write-Host "Finished. See $file for the results" -ForegroundColor Green

And here’s the final result in Internet Explorer.

Ok, maybe you don’t have a compelling need for this exact script, but I hope you picked up on the importance of writing code for re-use and taking advantage of the pipeline.

If you’d like to try my code out for yourself, including the graphic and CSS file, download this zip file.

PowerShell 3.0 Easy Rider

Today I gave an Live Meeting presentation for the PowerShell Virtual User Group. When the recording is posted I’ll update this post. I spoke about new features in Windows PowerShell 3.0 that I think will make it easier for people to use PowerShell more efficiently. I think they even might find it fun. Here is what I covered.

 

 

AGENDA
 New Help Options
 Default Parameter Values
 Simplified Syntax
 Improved Tab Completion
 Redirection Options
 Improved ISE Experience

The presentation started with some introductory slides, but most of the presentation was demo. As promised here is my presentation and a zip files with my demos and sample script.

Here is the link to the recording

Create a Master PowerShell Online Help Page

As I hope you know, PowerShell cmdlets can include links to online help. This is very handy because it is much easier to keep online help up to date. To see online help for a cmdlet use the -online parameter.

[cc lang="PowerShell"]
get-help get-wmiobject -online
[/cc]

I decided to take things to another level and create an HTML page with links to online help. Continue reading

New Comment Help

If you follow my blog I’m sure you noticed that I post a lot of advanced functions and scripts. While I don’t expect every one to be developing advanced functions, the closer you can get the more powerful your work. With the Scripting Games approaching I thought I’d offer up a little something to help take your scripts to the next level and that is adding comment based help. This is a specially structured comment block that you can insert into your functions and scripts. The comment block is parsed by Get-Help to produce the same type of help output you see with cmdlets. But creating the help comment can be tricky so I wrote a script based wizard. Continue reading

Get-NumberedContent v2

I wasn’t completely satisfied with the updated version of my Get-NumberedContent function. You should still refer to the earlier post for details on how to use the function. But I had some issues with the previous version and realized there were a few bugs. I’ve since updated the Get-NumberedContent function.

Continue reading

Summary Judgment

While working on a new article for REDMOND magazine about PowerShell 2.0, I wanted to get some cmdlet information. I wanted an easy way to see a list of cmdlets for a given verb or noun. Of course that is easily done with Get-Command. However this only gives my the definition.

After a little experimenting I found that I could get the help synopsis with the actual Get-Help cmdlet, not the Help function. So combining the two gives me the results I need.

PS C:\> gcm -noun job | select Name,@{Name="Synopsis";Expression={(get-help $_).synopsis}} | ft -auto -wrap

Name        Synopsis
—-        ——–
Get-Job     Gets Windows PowerShell background jobs that are running
            in the current session.
Receive-Job Gets the results of the Windows PowerShell background jobs
            in the current session.
Remove-Job  Deletes a Windows PowerShell background job.
Start-Job   Starts a Windows PowerShell background job.
Stop-Job    Stops a Windows PowerShell background job.
Wait-Job    Suppresses the command prompt until one or all of the
            Windows PowerShell background jobs running in the
            session are complete.

This should work for most Get-Command expressions. Although you may need to tweak a bit. Here’s my solution for discovering about aliases:

PS C:\> gcm -type alias | select Name,ResolvedCommandName,@{Name="Synopsis";Expression={(get-help $_).synopsis}} | ft -wrap -auto

Have fun.