Windows PowerShell Provider Quickstart
This topic explains how to create a Windows PowerShell provider that has basic functionality of creating a new drive. For general information about providers, see Windows PowerShell Provider Overview. For examples of providers with more complete functionality, see Provider Samples.
Writing a basic provider
The most basic functionality of a Windows PowerShell provider is to create and remove drives. In this example, we implement the System.Management.Automation.Provider.Drivecmdletprovider.Newdrive* and System.Management.Automation.Provider.Drivecmdletprovider.Removedrive* methods of the System.Management.Automation.Provider.Drivecmdletprovider class. You will also see how to declare a provider class.
When you write a provider, you can specify default drives-drives that are created automatically when the provider is available. You also define a method to create new drives that use that provider.
The examples provided in this topic are based on the AccessDBProviderSample02 sample, which is part of a larger sample that represents an Access database as a Windows PowerShell drive.
Setting up the project
In Visual Studio, create a Class Library project named AccessDBProviderSample. Complete the following steps to configure your project so that Windows PowerShell will start, and the provider will be loaded into the session, when you build and start your project.
Configure the provider project
Add the System.Management.Automation assembly as a reference to your project.
Click Project > AccessDBProviderSample Properties > Debug. In Start project, click Start external program, and navigate to the Windows PowerShell executable (typically c:\Windows\System32\WindowsPowerShell\v1.0\.powershell.exe).
Under Start Options, enter the following into the Command line arguments box:
-noexit -command "[reflection.assembly]::loadFrom(AccessDBProviderSample.dll' ) | import-module"
Declaring the provider class
Our provider derives from the System.Management.Automation.Provider.Drivecmdletprovider class. Most providers that provide real functionality (accessing and manipulating items, navigating the data store, and getting and setting content of items) derive from the System.Management.Automation.Provider.Navigationcmdletprovider class.
In addition to specifying that the class derives from System.Management.Automation.Provider.Drivecmdletprovider, you must decorate it with the System.Management.Automation.Provider.Cmdletproviderattribute as shown in the example.
namespace Microsoft.Samples.PowerShell.Providers
{
using System;
using System.Data;
using System.Data.Odbc;
using System.IO;
using System.Management.Automation;
using System.Management.Automation.Provider;
#region AccessDBProvider
[CmdletProvider("AccessDB", ProviderCapabilities.None)]
public class AccessDBProvider : DriveCmdletProvider
{
}
}
Implementing NewDrive
The System.Management.Automation.Provider.Drivecmdletprovider.Newdrive* method is called by the Windows PowerShell engine when a user calls the Microsoft.PowerShell.Commands.NewPSDriveCommand cmdlet specifying the name of your provider. The PSDriveInfo parameter is passed by the Windows PowerShell engine, and the method returns the new drive to the Windows PowerShell engine. This method must be declared within the class created above.
The method first checks to make sure both the drive object and the drive root that were passed in exist, returning null
if either of them do not. It then uses a constructor of the internal class AccessDBPSDriveInfo to create a new drive and a connection to the Access database the drive represents.
protected override PSDriveInfo NewDrive(PSDriveInfo drive)
{
// Check if the drive object is null.
if (drive == null)
{
WriteError(new ErrorRecord(
new ArgumentNullException("drive"),
"NullDrive",
ErrorCategory.InvalidArgument,
null));
return null;
}
// Check if the drive root is not null or empty
// and if it is 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;
}
The following is the AccessDBPSDriveInfo internal class that includes the constructor used to create a new drive, and contains the state information for the drive.
internal class AccessDBPSDriveInfo : PSDriveInfo
{
/// <summary>
/// A reference to the connection to the database.
/// </summary>
private OdbcConnection connection;
/// <summary>
/// Initializes a new instance of the AccessDBPSDriveInfo class.
/// The constructor takes a single argument.
/// </summary>
/// <param name="driveInfo">Drive defined by this provider</param>
public AccessDBPSDriveInfo(PSDriveInfo driveInfo)
: base(driveInfo)
{
}
/// <summary>
/// Gets or sets the ODBC connection information.
/// </summary>
public OdbcConnection Connection
{
get { return this.connection; }
set { this.connection = value; }
}
}
Implementing RemoveDrive
The System.Management.Automation.Provider.Drivecmdletprovider.Removedrive* method is called by the Windows PowerShell engine when a user calls the Microsoft.PowerShell.Commands.RemovePSDriveCommand cmdlet. The method in this provider closes the connection to the Access database.
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 the ODBC connection to the drive.
AccessDBPSDriveInfo accessDBPSDriveInfo = drive as AccessDBPSDriveInfo;
if (accessDBPSDriveInfo == null)
{
return null;
}
accessDBPSDriveInfo.Connection.Close();
return accessDBPSDriveInfo;
}