Developing with Windows PowerShell

This article provides a brief overview of Windows PowerShellâ„¢ and then describes how to create custom cmdlets and a Windows PowerShell snap-in to register the cmdlets. In the companion topic, Windows PowerShell in DinnerNow, the concepts discussed here are illustrated more fully with code from the DinnerNow.net sample application.

Overview

Windows PowerShell is the new standard Windows command-line shell. Windows PowerShell includes a runtime engine, data providers, core commands (known as cmdlets), a new scripting language, and an interactive prompt. Windows PowerShell is completely object-oriented and processes cmdlets, script files (.ps1), and executable files.

The Windows PowerShell runtime provides the operating environment. The runtime must be hosted in an application, which by default is PowerShell.exe. The hosting application communicates with the Windows PowerShell runtime through a runspace. For more information, see How Windows PowerShell Works.

A Windows PowerShell provider exposes stored data through virtual drives and common navigation commands. The FileSystem, Registry, and Environment providers are a few examples of the providers included with Windows PowerShell. For more information, see Navigating Windows PowerShell and How to Create a Windows PowerShell Provider.

A cmdlet is a specialized .NET type that represents a command built to run in Windows PowerShell. Windows PowerShell includes a library of more than a hundred core cmdlets (see the Microsoft.PowerShell.Commands namespace), and this library can be extended with custom cmdlets. Custom cmdlets are installed in the Windows PowerShell environment using a Windows PowerShell snap-in (unrelated to MMC snap-ins).

The Windows PowerShell runtime includes a command-line parser. When the parser encounters an executable file, the parser passes any command-line arguments directly to the executable, which is launched in a separate process. When the parser encounters a cmdlet, the parser binds any command-line arguments to properties of the cmdlet known as cmdlet parameters. The cmdlet has access to the command-line arguments without having to parse a string array containing the arguments.

The output of one cmdlet can be input to another cmdlet through the use of a pipeline. Interactively, a pipeline is specified using the | operator. Programmatically, a pipeline is represented by the Pipeline class. Each cmdlet has one input pipeline and at least two output pipelines (the standard output pipeline and an error pipeline).

Creating Custom Cmdlets

A custom cmdlet is derived from one of the following classes.

Class

Description

Cmdlet

The cmdlet does not require or have access to the Windows PowerShell runtime.

PSCmdlet

The cmdlet requires and has access to the Windows PowerShell runtime, which allows the cmdlet to call scripts, access Windows PowerShell providers, and access the current session state. The PSCmdlet class is derived from the Cmdlet class.

The derived class must be public and decorated with the CmdletAttribute attribute, which identifies the class as a cmdlet and defines the cmdlet's name.

Naming

Cmdlets are named using a verb-noun pair, where the verb indicates the action taken and the noun indicates the item(s) acted upon. For consistency, verbs are chosen from the set of predefined verbs provided by Windows PowerShell. These verbs are constant fields declared in the following static classes from the System.Management.Automation namespace. For more information, see Cmdlet Verb Names.

Class

Examples

VerbsCommon

Get, Set, Add, Remove, New

VerbsCommunication

Connect, Disconnect, Read, Write

VerbsData

Compare, Convert, Export, Import

VerbsDiagnostic

Debug, Ping, Trace

VerbsLifecycle

Enable, Disable, Start, Restart, Stop

VerbsSecurity

Block, Unblock, Grant, Revoke

The following code example shows a minimal cmdlet declaration, which defines the command Get-DNService.

using System.Management.Automation;

[Cmdlet(VerbsCommon.Get, "DNService")]
public class GetDNService : PSCmdlet
{
    protected override void ProcessRecord() { ... }
}

Input Processing

The derived cmdlet class must override at least one of its base class input-processing methods that is called by the pipeline processor, as described in the following table. For more information, see Cmdlet Lifecycle.

Method

Description

BeginProcessing

Called once to perform pre-processing and initialization before any piped-in objects are processed.

ProcessRecord

Processes an object in the pipeline. This method must be overridden if the cmdlet accepts pipeline input and is called once for every object piped-in to the cmdlet.

EndProcessing

Called once to perform post-processing after all piped-in objects have been processed. If the pipeline is stopped asynchronously, such as when the user cancels processing using the CTRL+C key combination, the StopProcessing method is called, and EndProcessing is not called.

Cmdlet Parameters

A cmdlet property that gets its value from the command-line or input pipeline is known as a "cmdlet parameter". Cmdlet parameters are bound to a piped-in object by the Windows PowerShell runtime. To create a cmdlet parameter, decorate a public property with a ParameterAttribute attribute that has one of the following properties set to true.

Property

Description

ValueFromPipeline

The cmdlet parameter is set to the piped-in object itself.

ValueFromPipelineByPropertyName

The cmdlet parameter is set with a property of the piped-in object that has the same name or alias as the cmdlet parameter.

Other ParameterAttribute properties are described in the following table.

Property

Description

Mandatory

The cmdlet parameter must be supplied. If this property is specified and the cmdlet parameter is not supplied by the piped-in object, by default, the user is prompted for the value.

Position

The position in the pipeline of the piped-in object that is used to set the cmdlet parameter.

HelpMessage

A short description of the cmdlet parameter.

For more information, see ParameterAttribute Declaration and Cmdlet Parameters. The following code example shows the declaration of a mandatory cmdlet parameter that receives its value from the Name property of the first object in the input pipeline.

private string _Name = "";

[Parameter(
    Mandatory = true,
    Position = 0,
    ValueFromPipelineByPropertyName = true,
    HelpMessage = "Name of the service")]
[ValidateNotNullOrEmpty]
public string Name
{
    get { return _Name; }
    set { _Name = value; }
}

Some of the other attributes that can be applied to a cmdlet parameter are described in the following table.

Attribute

Description

AliasAttribute

Allows a cmdlet parameter to be referred to by a different name.

AllowNullAttribute

Allows a piped-in object or its property to be null when passed to a mandatory cmdlet parameter. Other examples of this type include the AllowEmptyStringAttribute and AllowEmptyCollectionAttribute attributes.

ValidateNotNullAttribute

Causes the Windows PowerShell runtime to validate that the piped-in object or its property is not null before being passed to a non-mandatory cmdlet parameter. Other examples of validation attributes include the ValidateLengthAttribute and ValidateNotNullOrEmptyAttribute attributes.

Output Processing

To return data to the pipeline, use the overloaded Cmdlet.WriteObject methods. If the returned object is an enumerable collection, Windows PowerShell can iterate over the collection, passing each member to the next item in the pipeline. Methods belonging to the Console class, such as Read and Write, should not be used because they bypass the Windows PowerShell pipeline.

Other Cmdlet output methods are described in the following table.

Method

Description

WriteCommandDetail

Writes information to the execution log.

WriteDebug

Writes a debug message to the host.

WriteError

Writes an ErrorRecord about a non-fatal error to the error pipeline.

WriteProgress

Writes a ProgressRecord to the output pipeline.

WriteVerbose

Writes a general message to the output pipeline.

WriteWarning

Writes a warning message to the output pipeline.

To use a custom cmdlet, the cmdlet must be registered with Windows PowerShell using a Windows PowerShell snap-in, which is discussed in the following section.

Creating, Installing, and Adding a Windows PowerShell Snap-in

Windows PowerShell snap-ins are used to register custom Windows PowerShell cmdlets, providers, types, and formats. The following sections discuss how to create, install, and add a Windows PowerShell snap-in.

Cc303698.collapse_all(en-us,MSDN.10).gifCreating a Windows PowerShell Snap-in

A Windows PowerShell snap-in is a class derived from one of the following PSSnapInInstaller types.

Class

Description

PSSnapIn

Used to register all the cmdlets and providers found in the same assembly as the Windows PowerShell snap-in class.

CustomPSSnapIn

Used to register a subset of the cmdlets and providers found in one or more assemblies.

The derived class must be public and decorated with the RunInstallerAttribute attribute set to true, which allows the Installer tool (Installutil.exe) to install the class.

The PSSnapInInstaller class exposes the following string properties that must be overridden by the snap-in.

Property

Description

Name

The snap-in is registered under this name.

Description

A description of the snap-in.

Vendor

The vendor of the snap-in.

The PSSnapIn and CustomPSSnapIn classes expose the following string array properties that provide registration for custom types and formats. Custom and extended types used with Windows PowerShell are specified using an XML file with the .types.ps1xml extension. Custom display formatting of the types used by the cmdlets are specified using an XML file with the .format.ps1xml extension. For more information, see Extending Object Types and Formatting.

Property

Description

Types

A list of files (*.types.ps1xml) that define custom and extended types used by the cmdlets.

Formats

A list of files (*.format.ps1xml) that define formatting for the types used by the cmdlets.

The following code example shows a basic Windows PowerShell snap-in declaration.

using System.ComponentModel;
using System.Management.Automation;

[RunInstaller(true)]
public class DinnerNowPSSnapIn : PSSnapIn
{
    // ...
}

For more information, see How to Create a Windows PowerShell Snap-in.

Cc303698.collapse_all(en-us,MSDN.10).gifInstalling and Adding the Windows PowerShell Snap-in

The following steps are required to use a Windows PowerShell snap-in.

  1. Build the Windows PowerShell snap-in assembly.

  2. Run the Installer tool on the assembly.

    Installutil DinnerNow.Management.PS.dll
    

    The Installer tool registers the Windows PowerShell snap-in under the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\PowerShellSnapIns key using the snap-in's Name property.

    To confirm registration in a Windows PowerShell session, type:

    Get-PSSnapin -registered
    
  3. Add the snap-in to a Windows PowerShell session or runspace.

    The Windows PowerShell snap-in must be added to a Windows PowerShell session or runspace to use the registered cmdlets and providers. To add the snap-in to a Windows PowerShell session, invoke the Add-PSSnapin cmdlet:

    Add-PSSnapin DinnerNowPS
    

    The next section describes how to add the snap-in to a runspace.

For more information, see How to Register Cmdlets, Providers, and Host Applications.

Hosting Windows PowerShell

A Windows PowerShell runspace provides the ability to programmatically invoke a pipeline and execute cmdlets. The RunspaceFactory class creates a Runspace instance, using a RunspaceConfiguration instance to add a previously registered Windows PowerShell snap-in. A Windows PowerShell execution environment is created when the runspace is opened. The following code example shows the creation and opening of a runspace.

using System.Management.Automation;
using System.Management.Automation.Runspaces;

RunspaceConfiguration config = RunspaceConfiguration.Create();

PSSnapInException warning;
config.AddPSSnapIn("DinnerNowPS", out warning);

Runspace runspace = RunspaceFactory.CreateRunspace(config);
runspace.Open();

To execute a cmdlet, a Pipeline instance is created in the runspace and loaded with the command associated with the cmdlet. The pipeline is invoked, and the results from executing the cmdlet are returned, as shown in the following code example.

Pipeline pipe = runspace.CreatePipeline();
Command command = new Command("Get-DNService");
pipe.Commands.Add(command);
Collection<PSObject> results = pipe.Invoke(); 

For more information, see Configuring a Runspace Using a Windows PowerShell Snap-in.

See Also

Concepts

Design Highly Manageable Applications

Windows PowerShell in DinnerNow

Developing with Microsoft Management Console

Other Resources

Windows PowerShell

Windows PowerShell Blog

Cmdlet Development Guidelines

Windows PowerShell Snap-ins

Extend Windows PowerShell With Custom Commands