Constructing your First PowerShell Provider
Getting Started and Drive
Like all .NET development PowerShell development starts
with referencing a set of assemblies.
System.Management.Automation
contains most of
what you'll need for building PowerShell components.
System.Configuration.Install
is another useful
assembly I'll discuss later in the article.
In the sample, the Provider is implemented in the
TestPSProvider
class. As I stated earlier, I'm
implementing a Navigation Provider so the base class
inherits from NavigationCmdLetProvider
. Aside
from selecting a Provider base class, a Provider class
requires the CmdLetProvider
attribute. Below
is the Provider class definition.
[CmdletProvider("TestPSProvider", ProviderCapabilities.None)] public class TestPSProvider : NavigationCmdletProvider {
PowerShell Provider state is stored in a Drive. Drives
typically inherit from PSDriveInfo
. The sample
Drive class is called TestDriveInfo
. The
TestDriveInfo
class appears below.
internal class TestDriveInfo : PSDriveInfo { private TraceTest _trace = new TraceTest("PS"); public TraceTest TraceMessage { get { return _trace; } } public TestDriveInfo(PSDriveInfo driveInfo) : base(driveInfo) { string somethingToSave = ""; somethingToSave = "Something"; _trace.WriteLine("PSDriveInfo " + driveInfo.Description + " " + driveInfo.Root + " " + driveInfo.Name + " " + driveInfo.Provider.Name + " " + driveInfo.Provider.Description); this.SomethingToSave = somethingToSave; } public string SomethingToSave { get; protected set; } }
Aside from storing state, the Drive can be considered the
root of a Path. Drive naming choices appear in PowerShell.
To create drives, a PowerShell Provider must override
InitializeDefaultDrives
, the function appearing
below.
protected override System.Collections.ObjectModel.Collection<PSDRIVEINFO> InitializeDefaultDrives() { System.Collections.ObjectModel.Collection<PSDRIVEINFO> col = new System.Collections.ObjectModel.Collection<PSDRIVEINFO>(); TraceTestPSOut("BEGIN InitializeDefaultDrives"); PSDriveInfo info = new PSDriveInfo("TestPS", this.ProviderInfo, _pathSeparator, "Default Root", PSCredential.Empty); col.Add(NewDrive(info)); TraceTestPSOut("END InitializeDefaultDrives"); return col; }
Most of the really interesting parts of a PowerShell Provider relate to the "item" CmdLets. Item CmdLet processing is handled in the sample code by the functions in the Item and Container regions.
Item and Container
Run the "get-command
" Cmdlet and you'll
notice a lot of CmdLets ending in "-Item", a few examples
are: New-Item, Copy-Item, and Clear-Item. Invoking these
CmdLets changes data in the Provider calling similarly named
functions among the Item and Container Regions in the Sample
application. An annotated view of the Item and Container
regions appears below.
protected override bool ItemExists(string path) protected override void ClearItem(string path) protected override void GetItem(string path) protected override void SetItem(string path, object value) protected override void CopyItem(string path, string copyPath, bool recurse) protected override void GetChildItems(string path, bool recurse)
Earlier I mentioned the hierarchy of Providers. The Item
region corresponds with functions on the
ItemCmdLetProvider
and the Container region
corresponds to the ContainerCmdLetProvider
. The
remaining functionality is supplied by the Navigation region
functions. Before I cover Navigation I want to briefly
touch on Dynamic Parameters.
Page 2 of 3
This article was originally published on October 23, 2009