Key Concepts for Writing Cmdlets for the SharePoint Management Shell
Published: May 2010
There are several key concepts that are instrumental when you write Windows PowerShell cmdlets for SharePoint. While not exhaustive, the content that follows lists some of the important concepts that support the implementation of Windows PowerShell for SharePoint.
Although users enter parameter values as strings, Windows PowerShell attempts to convert these string values to their correct type, based on the parameter definition. Therefore, cmdlets that you write must provide a means to verify that parameter values that are passed into the cmdlet are of a valid data type.
Avoid passing parameters of type string or integer unless all values of that type are valid for the parameter. Instead, define a class that further restricts the range and format of the parameters. In addition, validate parameters by using the Parse(String) method of the parameter type. Windows PowerShell supports the use of the Parse() method to convert a string type to other data types.
Among the most significant of improvements that Windows PowerShell offers beyond the capabilities of Cmd.exe is the native ability for Windows PowerShell to combine a series of simple cmdlets into a pipeline, which is a series, or sequence, of commands. The pipeline allows output objects from one command to be passed (or piped) as input objects to subsequent commands. Command pipelines allow cmdlet developers to create complex, flexible command pipelines whose output objects can be saved and reused.
The process of piping relies on the cmdlet behavior wherein output objects are written to an object pipeline that is controlled by Windows PowerShell. This allows Windows PowerShell to attempt to match the object in the pipeline with the parameters of the subsequent cmdlet.
For piping to work, there must be an explicit correspondence between the output of the preceding cmdlet and the input of the following cmdlets. This correspondence can be at the object level, where the preceding object in the pipeline matches a parameter on the subsequent cmdlet. (This is called piping by value.) Alternatively, the correspondence can occur at the property level, where properties on the preceding object in the pipeline match parameters of the subsequent cmdlet.
Piping by Value
Piping by value means that a downstream cmdlet will consume an entire object from the pipeline, provided the object is of the correct type. Piping by value is commonly done by using Set cmdlets, where passing an entire object saves a read operation from a data source, and also with New cmdlets that support cloning. Piping by value is also used in cases where the downstream cmdlet cannot reread the object that is outputted by the upstream cmdlet.
PipeBind objects are special objects that are unique to Windows PowerShell for SharePoint and provide a second layer of specialized parameter sets that are optimized for SharePoint Foundation.
When you use SharePoint Foundation 2010 objects as cmdlet parameters, you should use the appropriate PipeBind object in place of the SharePoint object. This is essential, as it allows the user of the cmdlet to specify the value of the parameter in the appropriate way. The PipeBind object actually represents a layer that sits between the user input for a parameter and parameter object itself.
For example, a cmdlet that takes an SPSite parameter can take either the SPSite object itself, or the GUID identifier for that site collection, or else the URL of the site collection. It is the job of the SPSitePipeBind object to ensure that, regardless of which representation is presented by the Windows PowerShell runtime, the cmdlet itself is presented with the actual SPSite object.
PipeBind classes should not be bound to specific cmdlets but rather shared among all cmdlets. When you write a PipeBind cmdlet, ensure that it does not have any requirements that are specific to the cmdlet implementer.
Implementing a PipeBind Object
When implementing a PipeBind object, you must derive from the SPCmdletPipeBind<TCmdletObject> base class. To implement this class, do the following:
Implement the class constructor.
Override the object's Read() method.
The PipeBind class should have at least one constructor, although it may have more than one. When Windows PowerShell attempts to bind parameters, it iterates through the set of public constructors for a specified parameter and tries to match the parameter input with a PipeBind constructor. This means that for each possible type of input that represents a parameter, there must be a corresponding constructor.
The Read() method on the SPCmdletPipeBind<TCmdletObject> object returns the object type that is defined in the SharePoint Foundation object model: public virtual TCmdletObject Read().
Note that the Read() method must be overridden for each PipeBind object implementation, to ensure that the object model object is correctly retrieved. You can create additional overrides of the Read() method, as needed, to provide the required parameters.
Cmdlet Identity and Atomicity
Cmdlets must have an Identity parameter that specifies the object on which to act. When you write cmdlets, you must specify a unique identifier as the value for the Identity parameter. Note, however, that new cmdlets will not initially have an identifier; only after instantiation of the object can its identifier exist.
Cmdlet execution should simulate atomicity. That is, a cmdlet should either succeed and bring the system into a changed state, or else it should fail cleanly and return the system to the state that existed prior to its execution. In other words, cmdlets must provide a method to restore system state in the event of a failure.