Creating a Windows PowerShell Drive Provider
This topic describes how to create a Windows PowerShell drive provider that provides a way to access a data store through a Windows PowerShell drive. This type of provider is also referred to as Windows PowerShell drive providers. The Windows PowerShell drives used by the provider provide the means to connect to the data store.
The Windows PowerShell drive provider described here provides access to a Microsoft Access database. For this provider, the Windows PowerShell drive represents the database (it is possible to add any number of drives to a drive provider), the top-level containers of the drive represent the tables in the database, and the items of the containers represent the rows in the tables.
Defining the Windows PowerShell Provider Class
Your drive provider must define a .NET class that derives from the System.Management.Automation.Provider.Drivecmdletprovider base class. Here is the class definition for this drive provider:
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : DriveCmdletProvider
Notice that in this example, the System.Management.Automation.Provider.Cmdletproviderattribute attribute specifies a user-friendly name for the provider and the Windows PowerShell specific capabilities that the provider exposes to the Windows PowerShell runtime during command processing. The possible values for the provider capabilities are defined by the System.Management.Automation.Provider.Providercapabilities enumeration. This drive provider does not support any of these capabilities.
Defining Base Functionality
As described in Design Your Windows PowerShell Provider, the System.Management.Automation.Provider.Drivecmdletprovider class derives from the System.Management.Automation.Provider.Cmdletprovider base class that defines the methods needed for initializing and uninitializing the provider. To implement functionality for adding session-specific initialization information and for releasing resources that are used by the provider, see Creating a Basic Windows PowerShell Provider. However, most providers (including the provider described here) can use the default implementation of this functionality that is provided by Windows PowerShell.
Creating Drive State Information
All Windows PowerShell providers are considered stateless, which means that your drive provider needs to create any state information that is needed by the Windows PowerShell runtime when it calls your provider.
For this drive provider, state information includes the connection to the database that is kept as part of the drive information. Here is code that shows how this information is stored in the System.Management.Automation.PSDriveinfo object that describes the drive:
internal class AccessDBPSDriveInfo : PSDriveInfo
{
private OdbcConnection connection;
/// <summary>
/// ODBC connection information.
/// </summary>
public OdbcConnection Connection
{
get { return connection; }
set { connection = value; }
}
/// <summary>
/// Constructor that takes one argument
/// </summary>
/// <param name="driveInfo">Drive provided by this provider</param>
public AccessDBPSDriveInfo(PSDriveInfo driveInfo)
: base(driveInfo)
{ }
} // class AccessDBPSDriveInfo
Creating a Drive
To allow the Windows PowerShell runtime to create a drive, the drive provider must implement the System.Management.Automation.Provider.Drivecmdletprovider.Newdrive* method. The following code shows the implementation of the System.Management.Automation.Provider.Drivecmdletprovider.Newdrive* method for this drive provider:
protected override PSDriveInfo NewDrive(PSDriveInfo drive)
{
// check if drive object is null
if (drive == null)
{
WriteError(new ErrorRecord(
new ArgumentNullException("drive"),
"NullDrive",
ErrorCategory.InvalidArgument,
null)
);
return null;
}
// check if drive root is not null or empty
// and if its an existing file
if (String.IsNullOrEmpty(drive.Root) || (File.Exists(drive.Root) == false))
{
WriteError(new ErrorRecord(
new ArgumentException("drive.Root"),
"NoRoot",
ErrorCategory.InvalidArgument,
drive)
);
return null;
}
// create a new drive and create an ODBC connection to the new drive
AccessDBPSDriveInfo accessDBPSDriveInfo = new AccessDBPSDriveInfo(drive);
OdbcConnectionStringBuilder builder = new OdbcConnectionStringBuilder();
builder.Driver = "Microsoft Access Driver (*.mdb)";
builder.Add("DBQ", drive.Root);
OdbcConnection conn = new OdbcConnection(builder.ConnectionString);
conn.Open();
accessDBPSDriveInfo.Connection = conn;
return accessDBPSDriveInfo;
} // NewDrive
Your override of this method should do the following:
Verify that the System.Management.Automation.PSDriveinfo.Root* member exists and that a connection to the data store can be made.
Create a drive and populate the connection member, in support of the
New-PSDrive
cmdlet.Validate the System.Management.Automation.PSDriveinfo object for the proposed drive.
Modify the System.Management.Automation.PSDriveinfo object that describes the drive with any required performance or reliability information, or provide extra data for callers using the drive.
Handle failures using the System.Management.Automation.Provider.Cmdletprovider.WriteError method and then return
null
.This method returns either the drive information that was passed to the method or a provider-specific version of it.
Attaching Dynamic Parameters to NewDrive
The New-PSDrive
cmdlet supported by your drive provider might require additional parameters. To
attach these dynamic parameters to the cmdlet, the provider implements the
System.Management.Automation.Provider.Drivecmdletprovider.Newdrivedynamicparameters*
method. This method returns an object that has properties and fields with parsing attributes similar
to a cmdlet class or a
System.Management.Automation.Runtimedefinedparameterdictionary
object.
This drive provider does not override this method. However, the following code shows the default implementation of this method:
Removing a Drive
To close the database connection, the drive provider must implement the System.Management.Automation.Provider.Drivecmdletprovider.Removedrive* method. This method closes the connection to the drive after cleaning up any provider-specific information.
The following code shows the implementation of the System.Management.Automation.Provider.Drivecmdletprovider.Removedrive* method for this drive provider:
protected override PSDriveInfo RemoveDrive(PSDriveInfo drive)
{
// check if drive object is null
if (drive == null)
{
WriteError(new ErrorRecord(
new ArgumentNullException("drive"),
"NullDrive",
ErrorCategory.InvalidArgument,
drive)
);
return null;
}
// close ODBC connection to the drive
AccessDBPSDriveInfo accessDBPSDriveInfo = drive as AccessDBPSDriveInfo;
if (accessDBPSDriveInfo == null)
{
return null;
}
accessDBPSDriveInfo.Connection.Close();
return accessDBPSDriveInfo;
} // RemoveDrive
If the drive can be removed, the method should return the information passed to the method through
the drive
parameter. If the drive cannot be removed, the method should write an exception and then
return null
. If your provider does not override this method, the default implementation of this
method just returns the drive information passed as input.
Initializing Default Drives
Your drive provider implements the System.Management.Automation.Provider.Drivecmdletprovider.Initializedefaultdrives* method to mount drives. For example, the Active Directory provider might mount a drive for the default naming context if the computer is joined to a domain.
This method returns a collection of drive information about the initialized drives, or an empty collection. The call to this method is made after the Windows PowerShell runtime calls the System.Management.Automation.Provider.Cmdletprovider.Start* method to initialize the provider.
This drive provider does not override the System.Management.Automation.Provider.Drivecmdletprovider.Initializedefaultdrives* method. However, the following code shows the default implementation, which returns an empty drive collection:
Things to Remember About Implementing InitializeDefaultDrives
All drive providers should mount a root drive to help the user with discoverability. The root drive
might list locations that serve as roots for other mounted drives. For example, the Active Directory
provider might create a drive that lists the naming contexts found in the namingContext
attributes
on the root Distributed System Environment (DSE). This helps users discover mount points for other
drives.
Code Sample
For complete sample code, see AccessDbProviderSample02 Code Sample.
Testing the Windows PowerShell Drive Provider
When your Windows PowerShell provider has been registered with Windows PowerShell, you can test it by running the supported cmdlets on the command line, including any cmdlets made available by derivation. Let's test the sample drive provider.
Run the
Get-PSProvider
cmdlet to retrieve the list of providers to ensure that the AccessDB drive provider is present:PS>
Get-PSProvider
The following output appears:
Name Capabilities Drives ---- ------------ ------ AccessDB None {} Alias ShouldProcess {Alias} Environment ShouldProcess {Env} FileSystem Filter, ShouldProcess {C, Z} Function ShouldProcess {function} Registry ShouldProcess {HKLM, HKCU}
Ensure that a database server name (DSN) exists for the database by accessing the Data Sources portion of the Administrative Tools for the operating system. In the User DSN table, double-click MS Access Database and add the drive path
C:\ps\northwind.mdb
.Create a new drive using the sample drive provider:
new-psdrive -name mydb -root c:\ps\northwind.mdb -psprovider AccessDb`
The following output appears:
Name Provider Root CurrentLocation ---- -------- ---- --------------- mydb AccessDB c:\ps\northwind.mdb
Validate the connection. Because the connection is defined as a member of the drive, you can check it using the Get-PDDrive cmdlet.
Note
The user cannot yet interact with the provider as a drive, as the provider needs container functionality for that interaction. For more information, see Creating a Windows PowerShell Container Provider.
PS> (get-psdrive mydb).connection
The following output appears:
ConnectionString : Driver={Microsoft Access Driver (*.mdb)};DBQ=c:\ps\northwind.mdb ConnectionTimeout : 15 Database : c:\ps\northwind DataSource : ACCESS ServerVersion : 04.00.0000 Driver : odbcjt32.dll State : Open Site : Container :
Remove the drive and exit the shell:
PS> remove-psdrive mydb PS> exit
See Also
Creating Windows PowerShell Providers
PowerShell