A new feature of Windows PowerShell 2.0 lets you write custom cmdlet help for Windows PowerShell providers. This blog explains how to do it. (The topic will also be covered in excruciating detail in MSDN, but we don’t want you to wait.)
What’s a Provider?
A Windows PowerShell provider is a C# program that exposes a data store to Windows PowerShell through a Windows PowerShell drive (PSDrive). When users view the PSDrive, the data in the data store appears to be organized like a file system drive. The drive has a path and users can navigate through the data store by using file system navigation commands like CD and DIR.
For more information about designing a Windows PowerShell provider, see How to Create a Windows PowerShell Provider (http://go.microsoft.com/fwlink/?LinkID=152037).
If you’re a provider author (or the lucky writer), this feature is for you!
Custom cmdlets?
No, custom help topics for the provider cmdlets that your provider supports. Each provider supports a subset of the provider cmdlets that come with Windows PowerShell, such as Get-Item and Set-Location. You can find the complete list of provider cmdlets in about_Providers (http://go.microsoft.com/fwlink/?LinkID=113274).
A custom cmdlet help topic explains how the provider cmdlet works in your provider. You can specify different help files for different paths in your provider. And you can include examples of using the cmdlet in the paths of your provider drive.
How do users get custom cmdlet help?
When users are in a provider drive and they type “get-help” for a provider cmdlet, they get the custom cmdlet help for that provider (if it exists), instead of our generic cmdlet help topic.
C:\PS> cd wsman:\localhost\ClientCertificate
PS WSMAN:\localhost\ ClientCertificate> get-help new-item
NAME
New-Item
SYNOPSIS
Creates a new item. In this location, the New-Item command creates a new client certificate.
…
Users can also get custom cmdlet help by using the (new) Path parameter of Get-Help. Set the value of Path to a location in the provider drive.
C:\PS> get-help new-item -path wsman:\localhost\ClientCertificate
NAME
New-Item
SYNOPSIS
Creates a new item. In this location, the New-Item command creates a new client certificate.
…
What problem does this feature solve?
It solves a big problem and a small problem.
The small problem is that the help topics for the provider cmdlets are very generic. We couldn’t anticipate all of the ways that the cmdlets might be used in a provider drive, so we say correct, but not particularly useful, things like “gets the items in the drive.” Custom cmdlet help lets you say more useful things like “gets the files and folders ” or “gets the registry keys and entries.” More importantly, it lets you include examples of using the provider in your provider drive.
The big problem is that documentation of dynamic parameters is now too hard to find. Dynamic parameters that providers add to the provider cmdlets are described in the provider help topics. But because the dynamic parameters look just like the static ones, users don’t know where to look for parameter descriptions. It just looks like we forgot to doc a parameter.
(Guess where the Encoding parameter of Set-Content is documented? Yes, it’s in the FileSystem provider help topic.)
Custom cmdlet help allows us to document dynamic parameters along with the static parameters. For example, here’s the documentation of the Plugin and FileName parameters that the WSMAN provider adds to the New-Item cmdlet.
C:\PS> cd wsman:\localhost\plugin
PS WSMan:\localhost\Plugin> get-help new-item -parameter *
-Plugin <string>
Specifies the display name to use for the plug-in. If an error is returned by the plug-in, the display name
will be put in the error XML that is returned to the client application. The name is not locale specific.
Required? true
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false
-FileName <string>
Specifies the file name of the operations plug-in. Any environment variables that are put in this entry will
be expanded in the users’ context when a request is received. Because each user could have a different version
of the same environment variable, each user could have a different plug-in. This entry cannot be blank and must
point to a valid plug-in.
Required? true
Position? named
Default value
Accept pipeline input? false
Accept wildcard characters? false
…
How does it work?
When a user types “get-help” for a cmdlet, the help system gets the generic cmdlet help. But before returning it, it asks the provider if it wants to override the generic help. The provider should return null or it should return custom cmdlet help XML (for the MAML schema). If the provider returns cmdlet help, the help system merges the custom help with the generic help and returns it to the user.
Many providers have different objects in each path of their provider drive. To accommodate this variation, the custom cmdlet help design lets you write different help topics for each path of the drive. If your provider has the same objects in all paths, you can omit the path-specific elements of the custom cmdlet help design.
How do you do it?
Custom cmdlet help requires a few changes to the provider and to the provider help topic.
n Provider Changes
The provider must implement the new ICmdletProviderSupportsHelp interface. Instructions are in MSDN (http://go.microsoft.com/fwlink/?LinkID=152386).
public interface ICmdletProviderSupportsHelp
{
string GetHelpMaml(string cmdletName, string providerPath);
}
When Get-Help calls the GetHelpMaml() method for the provider with the cmdlet name and a friendly name for the provider path, the method returns the custom cmdlet help for that cmdlet help topic in the provider path. If the providerPath is null, GetHelpMaml() returns the first custom help topic that it finds for the specified cmdletName.
n Help File Changes
To add custom cmdlet help to an XML-based help file (dll-help.xml), you imbed standard cmdlet help (MAML) in the provider help XML, with the help of a few new XML tags.
Conceptually, it looks like this:
<providerHelp>
… # Provider Help Content …
<CmdletHelpPaths>
< CmdletHelpPath id=”providerPath“>
<command:command>
<command:details>
<command:name>
cmdletName
</command:name>
… # Custom cmdlet help content …
</command:command>
</CmdletHelpPath>
</CmdletHelpPaths>
</providerHelp>
New XML Tags
Many providers have different objects in each path of their provider drive. To accommodate this variation, the custom cmdlet help design lets you write different help topics for each path of the drive. If your provider has the same objects in all paths, you can omit the path-specific elements of the custom cmdlet help design.
There are two new XML tags for custom cmdlet help.
n CmdletHelpPaths: Contains all custom cmdlet help topics (for all provider paths).
n CmdletHelpPath: Contains the cmdlet help topics for a particular provider path. If your provider has the same objects in all paths, you need only one instance of this tag.
o ID attribute: [Optional] Specifies a friendly name for the provider path. If you are not specifying multiple paths, omit the attribute or use an empty string as the value (“”).
Here’s the XML skeleton of a help file that includes provider help. We’ll use the WSMAN provider help file as an example.
<?xml version=”1.0″ encoding=”utf-8″ ?>
<helpItems schema=”maml”>
…
# Standard cmdlet help #
…
<providerHelp>
<Name>
WSMan
</Name>
… # Standard provider help #
</RelatedLinks>
<CmdletHelpPaths>
<CmdletHelpPath ID=’ClientCertificate‘>
<command:command>
<command:details>
<command:name>
New-Item
</command:name>
… # Custom cmdlet help …
</command:command>
</CmdletHelpPath>
<CmdletHelpPath ID=’Listener‘>
<command:command>
<command:details>
<command:name>
New-Item
</command:name>
… # Custom cmdlet help …
</command:command>
</CmdletHelpPath>
</CmdletHelpPaths>
</providerHelp>
</helpItems>
Merged Help Content
To save you from having to rewrite an entire cmdlet help topic, the custom cmdlet help topic is actually a combination of the generic help topic and the elements that you add.
Some of the cmdlet help topic elements that you write replace the generic elements. Others are appended to the generic elements. The following table shows the rules. (You cannot change them.)
Notice that dynamic parameters appear before the static ones (they’re prepended), but your custom examples replace the generic examples in the help file and your custom descriptions of static parameters replace the generic parameter descriptions.
Field |
Action |
Name |
None |
Synopsis |
Replace |
Syntax |
Append |
Detailed Description |
Append |
Parameters |
Prepend |
Parameter Description |
Replace |
Input Type |
Replace |
Return Type |
Replace |
Notes |
Append |
Examples |
Replace |
Related Links |
Replace |
Remarks |
None |
Role |
Replace |
Functionality |
Replace |
Component |
Replace |
Okay, JuneB, where are yours?
If custom cmdlet help is such a great idea, then where is the custom cmdlet help for the core providers, such as FileSystem, Registry, and Certificate?
Well, let’s just say that we were really busy. The core providers have not yet implemented the ICmdletProviderSupportsHelp interface, so we can’t display custom cmdlet help. But we’ll be working on it for a future release of Windows PowerShell.
In the meantime, feel free to ask questions. You can submit them by adding comments to this blog and I’ll update with answers if necessary.
June Blender [MSFT]
juneb@microsoft.com
Get-Help -online: http://technet.microsoft.com/en-us/library/bb978525.aspx
0 comments