Chapter 13 PowerShell as a Management Interface

IN THIS CHAPTER

This chapter explains how PowerShell can be used as a management interface for applications. With new releases, such as Exchange 2007, Microsoft has built the management interface upon the foundation of PowerShell. For instance, when an administrator makes a change in the Microsoft Management Console (MMC) for Exchange, a PowerShell cmdlet is executed in the background to process the request. For developers who want to manage their own applications through PowerShell, Microsoft has released the PowerShell Software Development Kit (SDK) that can be leveraged to create custom cmdlets—which can then be called from a custom command shell, Windows application, or MMC snap-in.

This chapter covers creating a custom cmdlet, creating a custom snap-in, adding parameters to a custom cmdlet, and several other advanced features. Additionally, the scenario covers creating an MMC 3.0 snap-in that uses Yahoo! Maps geocoding functionality to pull coordinates for a street address.

NOTE

All the source code referenced in this chapter are available at www.informit.com/title/9789780768687187.

Getting Started

The examples in this chapter are written in C# using Microsoft Visual Studio 2008 Express Edition (Visual Basic .NET is also supported). This is a free development tool from Microsoft and is highly recommended (although not required, one could just as easily write a custom cmdlet in Notepad).

NOTE

The entire Microsoft Visual Studio Express Edition suite can be downloaded here:

http://www.microsoft.com/express

Definitions

For those new to .NET development, here are some definitions for commonly used words that will be seen throughout this chapter (several of these definitions are also found in Chapter 3, “Advanced PowerShell Concepts”):

Namespace—A hierarchical grouping of objects. For example: The System.Net.Mail is the namespace where the mail-related objects are located.

Class—An object template that contains methods and properties. For example: The SmtpClient class within the System.Net.Mail namespace can be used to send an email message.

Method—A function that can be executed by a class object. For example: The SmtpClient class exposes a method named Send.

Property—A variable that can be set or obtained from a class object. For example: The Body property in the MailMessage class contains the text in the body of an email message.

Library—A .dll file that contains compiled .NET code. For example: The System.Net.dll library contains compiled code pertaining to the System.Net namespace.

Global Assembly Cache—A collection of .NET libraries that are built into the .NET framework.

The PowerShell SDK

The PowerShell SDK is included in the Microsoft Windows Software Development Kit for Vista and .NET 3.0 Runtime Components. Although the SDK was released for Windows Vista, it is also supported on Windows XP SP2 and Windows 2003 SP1 or later.

NOTE

To download the Microsoft Windows Software Development Kit for Vista and .NET 3.0 Runtime Components, go to the following location:

http://go.microsoft.com/fwlink/?LinkId=79482

Installation Instructions

Installing the Microsoft Windows Software Development Kit is a straightforward process.

1. Click Next at the Welcome Screen (see Figure 13.1).

Figure 13.1. Vista SDK Welcome Screen

Image

2. Accept the license agreement and click Next (see Figure 13.2).

Figure 13.2. Vista SDK License Agreement

Image

3. Leave the default install location and click Next (see Figure 13.3).

Figure 13.3. Vista SDK installation path

Image

4. Select the .NET Development Tools under Developer Tools / Windows Development Tools (see Figure 13.4).

Figure 13.4. Vista SDK component selection

Image

5. Click Next to begin the installation (see Figure 13.5).

Figure 13.5. Vista SDK license install

Image

6. Click Finish (see Figure 13.6).

Figure 13.6. Vista SDK finished

Image

Creating a Custom Cmdlet

Creating a custom cmdlet is a snap. The following example demonstrates how to create a simple cmdlet that returns “Hello World!”

Naming Conventions

The first step in creating a cmdlet is to determine a name. PowerShell cmdlet names are standardized using the verb-noun format. Each cmdlet begins with a verb that describes what type of command the cmdlet is going to execute—and ends with a noun that describes what object the cmdlet is going to execute against. For instance, the commonly used Get-Command cmdlet begins with the verb “Get,” which is the type of command the cmdlet is going to execute. It ends with the noun “Command,” which is what the cmdlet is going to execute against.

When naming a custom cmdlet, Microsoft has provided several sets of standard verbs to choose from in the System.Management.Automation namespace. The classes include the following:

• VerbsCommon

• VerbsCommunications

• VerbsData

• VerbsDiagnostic

• VerbsLifecycle

• VerbsOther

• VerbsSecurity

Each of these classes contains commonly used verbs, such as the following:

• Get

• Set

• Start

• Stop

The noun should also be singular, not plural. So, for example, Get-Command is acceptable, but Get-Commands is not.

When selecting a name for a namespace or class, Microsoft recommends using the naming convention of ApplicationName.PowerShell.Commands for a namespace and VerbNounCommand for a class.

The following is an example of the correct naming convention from one of the SDK libraries, as displayed in the Visual Studio Object Browser (see Figure 13.7).

Figure 13.7. Visual Studio Object Browser

Image

Setting Up a Project

After the appropriate names are chosen, a new class for a custom cmdlet can be created. If Visual Studio is being used, create a new Class Library project named HelloWorld (see Figure 13.8).

Figure 13.8. New Visual Studio project

Image

Next, add a reference to the System.Management.Automation.dll by completing the following steps (see Figure 13.9).

Figure 13.9. Add a Visual Studio reference.

Image

1. From the toolbar, select Project >> Add Reference.

2. Click the browse tab. (The libraries from the PowerShell SDK are not loaded in the Global Assembly Cache so they won’t show up on the default list.)

3. Navigate to C:Program FilesReference AssembliesMicrosoft WindowsPowerShellv1.0 and select System.Management.Automation.dll.

4. Click OK.

Writing the Code

The required attributes for a new cmdlet class include a verb and a noun, as described previously. The class must also be a public class to be executed as a cmdlet from within PowerShell.

The two cmdlet classes are Cmdlet and PSCmdlet. The Cmdlet class is more flexible and can be called directly from other .NET code, whereas the PSCmdlet class must execute in a PowerShell runspace (but has the primary benefit of being able to call PowerShell scripts).

In the following example, the Cmdlet class has been inherited in the HelloWorld. PowerShell.Commands namespace. For the verb attribute, the VerbsCommon.Get property is used; for the noun attribute, “HelloWorld” is used. When executed from within PowerShell, the cmdlet name will be Get-HelloWorld.

image

image

A custom cmdlet must override one of the following methods that are contained in the Cmdlet and PSCmdlet classes: BeginProcessing, ProcessRecord, or EndProcessing. Each method is executed in sequence at a different phase of the cmdlet lifecycle, so the particular method that should be selected depends on whether one intends to process input from the pipeline.

If a custom cmdlet needs to perform any pre-processing before receiving pipeline input, you should use the BeginProcesses method. If the cmdlet must receive pipeline input, you should use the ProcessRecord method. If the cmdlet will not receive pipeline input, you should use the EndProcessing method.

To return data to the pipeline, you must use the WriteObject method and pass the output data.

In the following example, the ProcessRecord method has been overridden (details on handling input come later in the section “Creating Custom Parameters”), and the simple string “Hello World!” is sent to the pipeline.

image

image

Creating a Custom Snap-In

A PowerShell snap-in contains cmdlets that can be executed from within PowerShell. To execute a custom cmdlet, you must create a custom snap-in that is registered from within PowerShell.

The first step is to add a reference to the System.Configuration.Install library that is part of the Global Assembly Cache. This library is required to write a custom installer for our snap-in.

Next, create another public class and inherit PSSnapIn, which resides in the System.ComponentModel namespace. Microsoft recommends using the VerbNounPSSnapIn naming convention for these classes.

Finally, add the RunInstaller attribute so that installutil.exe can be invoked to register the snap-in after it is compiled.

In the following example, the custom PSSnapIn class has been named GetHelloWorldPSSnapIn.

image

image

Three required properties must be overridden for a custom snap-in: Name, Vendor, and Description.

image

image

The complete code for a custom cmdlet and snap-in displays as follows:

image

image

With the code completed, it can now be compiled into a .dll library. If Visual Studio is being used, select Build >> Build Solutions from the toolbar. To compile the code using the command line, use the following commands:

image

PS> $r = "$Env:ProgramFilesReference
AssembliesMicrosoftWindowsPowerShellv1.0System.Management.
Automation.dll"
PS> set-alias csc "$env:windir/Microsoft.NET/Framework/v2.0.50727/csc"
PS> csc /target:library /r:$r HelloWorld.cs

image

After the code has been compiled, the snap-in must be registered with PowerShell. Be aware that this requires administrator privileges, so do a RunAs if a low-privilege account is being used.

The following commands are used to register the snap-in:

image

PS> $HelloWorld =  HelloWorld.dll
PS> set-alias installutil
"$env:windirMicrosoft.NETFrameworkv2.0.50727installutil"
PS> installutil $HelloWorld

image

To confirm that the snap-in has been registered, run the Get-PSSnapIn cmdlet with the –registered parameter:

image

PS> Get-PSSnapIn –Registered

Name        : GetHelloWorldPSSnapIn
PSVersion   : 1.0
Description : Returns Hello World!

PS>

image

Add the snap-in to PowerShell with Add-PSSnapIn cmdlet:

image

PS> Add-PSSnapIn GetHelloWorldPSSnapIn

image

To confirm that our cmdlet is now available, run Get-Command Get-HelloWorld:

image

PS> Get-Command Get-HelloWorld

CommandType     Name
-----------     ----
Cmdlet          Get-HelloWorld

PS>

image

Finally, the custom cmdlet Get-HelloWorld can now be executed in PowerShell!

image

PS> Get-HelloWorld
Hello World!

image

Creating Custom Parameters

Cmdlets can accept two types of parameters: command-line parameters and pipeline parameters.

Command-line parameters come after the command and modify how the command operates. For instance, the Get-Command cmdlet returns a list of all available PowerShell commands. However, if the –name parameter is used, information on a specific command is returned.

Likewise, many cmdlets also accept parameters from the pipeline. For example, the Format-List cmdlet accepts objects from an upstream cmdlet and outputs it in a list format, as opposed to the more common table format.

Again, to create a custom parameter, the first step is to come up with a name. PascalCase, or capitalizing the first letter of each word, is the recommended format.

It is also recommended to use common parameter names that are already established, such as Name, ID, Property, and Location. This is particularly important when receiving input from the pipeline, because PowerShell has the functionality to match like-types.

NOTE

Microsoft maintains a list of recommended parameter names here:

http://msdn2.microsoft.com/en-us/library/ms714468(VS.85).aspx

In the following example, a public string property named Location has been created that inherits the Parameter class. Get and Set functionality has also been added:

image

image

To enable a cmdlet to accept pipeline parameters, set the ValueFromPipeline attribute to true.

image

image

Now that the parameter class is complete, the cmdlet must be modified to properly process any object that is received. In the following example, this has been accomplished by checking to determine whether the private myLocation string is null. If it is not null, an alternate message is output to the pipeline.

image

image

In the following example, the cmdlet is executed using no input, a command-line parameter, and a pipeline parameter, respectively:

image

PS> Get-HelloWorld
Hello World!
PS> Get-HelloWorld –Location "San Francisco"
Hello San Francisco!
PS> echo "Los Angeles" | Get-HelloWorld
Hello Los Angeles!

image

Advanced Parameter Functionality

In addition to the basic functionality of parameters outlined in this chapter, some advanced options are also useful.

Arrays

Arrays can be used to accept multiple instances of an object. In the following example, the single Location string has been changed to accept an array of strings:

image

image

The ProcessRecord override is then modified to output each string in the array:

image

image

Now the user can input multiple locations with a single command:

image

PS> Get-HelloWorld –Location "Portland","Sacramento"
Hello Portland!
Hello Sacramento!

image

Position

The Position = X property can be used to identify the order in which a parameter will appear after a command so that the user does not need to use the –Parameter command-line switch. In the following example, the Position property is set to zero, so the first object that follows the Get-HelloWorld command becomes the Location parameter value:

image

image

image

PS> Get-HelloWorld "Oakland"
Hello Oakland!

image

Mandatory

The Mandatory = true property can be used to enforce a parameter. If the user does not supply the parameter, PowerShell will prompt for it:

image

image

image

PS> Get-HelloWorld
cmdlet Get –HelloWorld at command pipeline position 1
Supply values for the following parameters:
Location: San Diego
Hello San Diego!

image

HelpMessage

The HelpMessage = string property can be used to add help to a parameter. In the following example, we set a help message with the value “Sample Help Message:”

image

image

image

PS> Get-HelloWorld
cmdlet Get -HelloWorld at command pipeline position 1
Supply values for the following parameters:
(Type !? for Help.)
Location: !?
Sample Help Message

image

Alias

The Alias attribute can be used to set an alternative name for a parameter. In the following example, we set an alias for the Location parameter named Loc:

image

image

image

PS> Get-HelloWorld –Loc "Seattle"
Hello Seattle!

image

Input Validation

Parameters also have excellent built-in support for input validation. This enables cmdlet developers to set limits on exactly what type of input is acceptable.

ValidateLength

The ValidateLength attribute can be used to ensure that an input value meets minimum and maximum length requirements. The first value is the minimum length, and the second value is the maximum length. In the following example, the minimum length is set to 5 characters, and the maximum length is set to 10 characters:

image

image

image

PS> Get-HelloWorld –Location "San"
Get-HelloWorld : Cannot validate argument because its length (3) is
too small. Specify a length that is greater than or equal to "5" and
try again.
At line:1 char:25
+ get-helloworld -location  <<<< "San"
PS> Get-HelloWorld -Location "San Francisco"
Get-HelloWorld : Cannot validate argument because its length (13) is
too long. Specify a length that is less than or equal to "10" and try
again.
At line:1 char:25
+ get-helloworld -location  <<<< "San Francisco"

image

ValidateRange

The ValidateRange attribute can be used to ensure than an input integer is within a predefined numeric range. The first value is the minimum value, and the second value is the maximum value. In the following example, the Location attribute has been changed to an int, and the ValidateRange attribute is set to accept a number between 5 and 10:

image

image

image

PS> Get-HelloWorld -Location 1
Get-HelloWorld : The argument (1) was smaller than the minimum range (5).
Specify a value greater than or equal to the MinRange value and try again.
At line:1 char:25
+ get-helloworld -location  <<<< 1
PS> Get-HelloWorld –Location 11
Get-HelloWorld : The argument (11) was greater than the maximum range (10).
At line:1 char:25
+ get-helloworld -location  <<<< 11

image

ValidatePattern

The ValidatePattern attribute can be used to ensure than an input integer meets a specific series of values. This is particularly useful for values, such as license plate numbers, that do not fall between a specific numeric range but still have a strict format that must be followed. In the following example, the ValidatePattern attribute is looking for a value that matches the California license plate format of number-letter-letter-letter-number-number-number:

image

image

image

PS> Get-HelloWorld –Location 0abc1234
Hello 0abc1234!
PS> Get-HelloWorld –Location 0abcd123
Get-HelloWorld : Cannot validate argument "0abcd123" because it does
not match pattern "[0-9][a-z][a-z][a-z][0-9][0-9][0-9]".
At line:1 char:25
+ get-helloworld -location  <<<< 0abcd123

image

ValidateSet

The ValidateSet attribute can be used to accept only a specific value or set of values. There is also an optional parameter IgnoreCase=Boolean to determine whether the parameter is case sensitive (the default is case insensitive). In the following example, San Bruno and San Jose are the only valid input values that will be accepted:

image

image

image

PS> Get-HelloWorld –Location "San Bruno"
Hello San Bruno!
PS> Get-HelloWorld –Location "San Jose"
Hello San Jose!
PS> Get-HelloWorld –Location "San Juan"
Get-HelloWorld : Cannot validate argument "San Juan" because it does
not belong to the set "San Bruno, San Jose".
At line:1 char:25
+ get-helloworld -location  <<<< "San Juan"

image

ValidateCount

The ValidateCount attribute can be used to accept a specific number of input values. This is useful if a parameter is an array that should be only of a specific size. In the following example, only two values can be input:

image

image

image

PS> Get-HelloWorld –Location "Las Vegas","Reno"
Hello Las Vegas!
Hello Reno!
PS> Get-HelloWorld –Location "Las Vegas","Reno","Lake Tahoe"
Get-HelloWorld : Cannot validate arguments because the number of
supplied arguments (3) exceeds the maximum number of allowed arguments
(2). Specify less than 2 arguments and try again.
At line:1 char:25
+ get-helloworld -location  <<<< "Las Vegas","Reno","Lake Tahoe"

image

Lastly, the following common parameter names are reserved and should not be used: Confirm, Debug, ErrorAction, ErrorVariable, OutBuffer, OutVariable, Verbose, and WhatIf. The following aliases are also reserved: db, ea, ev, ov, ob, and vb.

Supporting Get-Help

Get-Help is a commonly used cmdlet, and it is expected that any custom cmdlets support it.

Help for a custom cmdlet is written in a formatted XML file. This provides an easy way for a cmdlet developer to fill in the necessary fields so that the help is output in a standardized format.

The XML file must follow the standardized naming scheme, which is <libraryname>.dll-Help.xml. For the Get-HelloWorld cmdlet, the XML help file is named HelloWorld.dll-Help.xml.

When Get-Help is run against a cmdlet, several predefined sections are populated with data from the XML help file. Before proceeding, take a moment to run Get-Help Get-Command –full to see an example of what a complete help section looks like.

Header

After the XML file is created, the first step is to add the header. This provides the schema information, which sets the rules for how the XML file must be formatted and populated.

image

image

NOTE

It is important to remember that XML files are case sensitive.

Name and Synopsis

The first section of the XML file is the <command:details> node, which populates the Name and Synopsis sections of Get-Help.

The <command:name> node is required and must match the name of the cmdlet; otherwise, Get-Help returns an error.

The <command:verb> node is the verb portion of the cmdlet name.

The <command:noun> node the noun portion of the cmdlet name.

The <maml:description> node is actually what appears under the Synopsis section.

image

image

NOTE

The <maml:para> node appears frequently in the XML code and indicates a separate paragraph.

Syntax

The next section of the XML file is the <command:syntax> node, which populates the Syntax sections of Get-Help. If a cmdlet has multiple parameter sets, multiple syntaxItem nodes can be added for each set. Because the Get-HelloWorld cmdlet has only one parameter set, only one syntaxItem is supplied.

The <maml:name> node is the name of the cmdlet as it will appear in the Syntax section.

The <command:parameter> node contains several attributes:

required=booleanIndicates whether the parameter is required

globbing=booleanIndicates whether the parameter supports wildcards

pipelineInput=booleanIndicates whether the parameter supports pipeline input

position=intIndicates if the parameter supports the position attribute and what location it is at

The <command:parameterValue> node is the object type the parameter accepts.

Multiple <command:parameter> sub-nodes can be added when a cmdlet accepts multiple parameters.

image

image

NOTE

Be careful for typos in the cmdlet name and parameter name nodes, because they are not validated to match the actual values when the help file is registered.

Detailed Description

The next section of the XML file is the <maml:description> node, which populates the Detailed Description section of Get-Help.

image

image

Parameters

The next section of the XML file is the <maml:parameters> node, which populates the Parameters section of Get-Help. This section is different from the parameters that are displayed under the Syntax section and are intended to be more detailed.

The node structure is also essentially the same, with the exception of the new <maml:description> node, which contains a description of the parameter.

This section is visible when using the –Full or –Detailed command-line parameters of Get-Help.

image

image

Input Type

The next section of the XML file is the <command:inputTypes> node, which populates the Input Type section of Get-Help. The input type should indicate the object type that is accepted as input, such as a string.

Multiple Input Types can be specified using the sub-node <command:inputType>. The <dev:type> node contains the actual value that is returned.

image

image

Return Type

The next section of the XML file is the <command:outputTypes> node, which populates the Return Type section of Get-Help. This is similar to the previous Input Type section, and it should also indicate the object type that is returned as output, such as a string.

image

image

Notes

The Notes section consists of both notes and examples.

The notes are populated by the <maml:alertSet> node. The <maml:title> node is the header that is displayed above the note, and the <maml:alert> node is the actual note itself.

image

image

The examples are populated by the <command:examples> node. Multiple examples can be supplied using the sub-node <command:example>.

The <maml:title> node should indicate the example number.

The <dev:code> node should include an example of the syntax to run the command.

The <dev:remarks> node should include an example of the output from the command.

image

image

Related Links

The <maml:relatedLinks> node populates the Related Links section of Get-Help. Typically, this section includes cmdlets that are often used in conjunction with the custom cmdlet.

Note that in this case the <maml:navagationLink> sub-node is different from the parent node. Multiple instances of <maml:navagationLink> can be supplied. The actual data is contained in the <maml:linkText> node.

image

image

Output

To include the XML help file when the cmdlet is registered, it must be in the same location as the compiled .dll library.

After it has been registered, it can now be accessed normally from Get-Help.

Here is the output from Get-Help Get-HelloWorld -full:

image

PS> Get-Help Get-HelloWorld -full
NAME
    Get-HelloWorld

SYNOPSIS
    Returns Hello World!

SYNTAX
    Get-HelloWorld [[-Location] [<string>]] [<CommonParameters>]

DETAILED DESCRIPTION
    Returns Hello World! or allows the user to supply a
           custom location!

PARAMETERS
    -Location [<string>]
        This parameter will be output as part of Hello
               Location!

        Required?                    false
        Position?                    0
        Default value                World
        Accept pipeline input?       true
        Accept wildcard characters?  false

    <CommonParameters>
        This cmdlet supports the common parameters: -Verbose, -Debug,
        -ErrorAction, -ErrorVariable, and -OutVariable. For more
information,

        type, "get-help about_commonparameters".

INPUT TYPE
    string

RETURN TYPE
    string

NOTES
    Additional Notes

        This is really just a simple cmdlet, there isn't
             much to say

    ----------  EXAMPLE 1  ----------

    Get-HelloWorld "San Francisco"

    This will return Hello San Francisco!

RELATED LINKS
    Get-Help

PS>

image

Runspaces

A runspace can be used to execute PowerShell commands from within a .NET-based application. The following example creates a simple .NET executable that calls the Get-HelloWorld cmdlet.

As with the previous example that creates a custom cmdlet, you must first add a Reference to the System.Management.Automation.dll.

At this point, the application looks as follows:

image

image

The next step is to create a runspace configuration. This is required to create a runspace and can be used to add a custom snap-in.

The following example adds the GetHelloWorldPSSnapIn:

image

image

Next, the runspace itself can be created using the runspace configuration.

The following example creates a runspace and then opens it:

image

image

After the runspace has been initialized, cmdlets can be called.

The following example calls the Get-HelloWorld cmdlet and sets the Location parameter:

image

image

Next, a pipeline object must be created. The pipeline object in the .NET executable functions just like a pipeline from within PowerShell. Multiple cmdlets can be called, and output can be passed down the chain.

In the following example, the command that was created previously is added to the pipeline. After the pipeline is invoked, it returns a PSObject collection.

NOTE

The Collection class is in the System.Collections.ObjectModel namespace, and the PSObject class is in the System.Management.Automation namespace.

image

image

The output is written to the console:

image

image

The complete source code looks like this:

image

image

After compiling the code into an executable, it can now be run:

image

PS> .HelloWorldConsole.exe
Hello San Dimas!

image

Scenario: Geocoding in MMC 3.0

As mentioned at the beginning of the chapter, the management interface for new Microsoft products is built upon the foundation of PowerShell. This gives administrators the ability to fully manage their products from the command line.

However, for most administrators, managing a product such as Exchange entirely from the command line is not practical. With MMC 3.0, Microsoft is wrapping the PowerShell cmdlets into a graphical user interface that enables any administrator to easily manage the product with a simple point-and-click.

In this scenario, Company ABC is working on a product to track the location of its customers so that it can determine when it makes sense to open a new shipping depot. Developers at Company ABC must come up with a way to resolve the longitude and latitude of each customer address.

Get-Coordinates Cmdlet

Yahoo! offers an excellent Geocoding API as part of its Yahoo! Maps web application. Developers at Company ABC decided to leverage this API for their Get-Coordinates cmdlet.

NOTE

For more information about the Yahoo! Geocoding API, visit this address: http://developer.yahoo.com/maps/rest/V1/geocode.html

The Get-Coordinates cmdlet must accept parameters for street, city, and state. These parameters will in turn be used to create a full web address from which the cmdlet will then receive a formatted XML file that contains the longitude and latitude.

Here is the complete source code for the cmdlet:

image

image

As with all cmdlets, the Get-Coordinates cmdlet must be compiled and registered with installutil.exe before it can be used in PowerShell.

image

PS> $GetCoordinates =  GetCoordinates.dll
PS> set-alias installutil
"$env:windirMicrosoft.NETFrameworkv2.0.50727installutil"
PS> installutil $GetCoordinates

image

Here is the output from the cmdlet after it has been run:

image

PS> Get-Coordinates -street "1600 Pennsylvania Ave" -city Washington
-state DC
38.898590,-77.036473,20006

image

Get-Coordinates User Control

MMC 3.0 snap-ins can be created using simple User Controls designed in Visual Studio. The User Control in this scenario creates a runspace and calls the Get-Coordinates cmdlet.

To create a User Control in Visual Studio, right-click on the project name inside the Solution Explorer and select Add >> User Control (see Figure 13.10).

Figure 13.10. Add a new Visual Studio User Control

Image

In the design view, a simple interface was created using the textbox and label controls, along with a button to initialize the search (see Figure 13.11).

Figure 13.11. The complete Geocode User Control

Image

The code-behind for the User Control is also straightforward. The cmdlet parameters are taken from their respective TextBox controls. A pipeline is created, the cmdlet is added to it, and then the pipeline is invoked. The resultant output is then converted into a string, split, and used to populate the result controls.

Here is the complete source code for the User Control code-behind:

image

image

Get-Coordinates MMC

The first step to create an MMC 3.0 snap-in is to add a reference to the Microsoft.ManagementConsole.dll library. Fortunately, this is included in the Microsoft Windows Software Development Kit for Vista, so there is nothing additional that needs to be installed.

NOTE

The default location for this file is in C:Program FilesReference AssembliesMicrosoftmmcv3.0.

Each snap-in must have a unique GUID. Microsoft has created a utility named guidgen.exe, which is the simplest way to create a new GUID.

After guidgen.exe is executed (see Figure 13.12), select Registry Format and click the Copy button.

Figure 13.12. GuidGen.exe

Image

Next, add a new class definition to the Visual Studio project. The new class inherits the SnapIn class. Two attributes are required: a GUID (which can be pasted in from the guidgen.exe application) and a DisplayName. The DisplayName displays under “Available snap-ins” when the snap-in is added to an MMC console.

Additionally, another new class that inherits the SnapInInstaller class is required so that installutil.exe can be used to register the snap-in.

image

image

MMC is designed to support multiple snap-ins, so each snap-in must have its own node. The DisplayName property of the node appears under “Console Root” after the snap-in is added to an MMC console.

The final code required is to create a FormViewDescription. Multiple types of FormViews can be used—the FormViewDescription is the class that is required to create a WinForm with a User Control.

In the following code, a new FormViewDescription is added, and the ControlType property is set to the GetCoordinatesControl that was created previously. The FormViewDescription is then added to the node.

image

image

Finally, the code must be compiled and registered with installutil.exe.

image

PS> $GetCoordinatesMMC =  GetCoordinatesMMC.dll
PS> set-alias installutil
"$env:windirMicrosoft.NETFrameworkv2.0.50727installutil"
PS> installutil $GetCoordinatesMMC

image

It can then be added to MMC and used as a snap-in (see Figure 13.13)!

Figure 13.13. Finished Geocode MMC snap-in

Image

Summary

In this chapter, you learned how to create a PowerShell cmdlet and how to execute that cmdlet from within an MMC 3.0 snap-in. Advanced functionality, such as creating parameters, supporting Get-Help, input validation, and creating runspaces in .NET were explained in detail.

PowerShell offers a new standard for command-line interfaces, and MMC 3.0 offers a new standard for GUIs. Now that Microsoft has established a precedent that its applications can be managed by both interfaces, users will begin to expect similar functionality in any third-party applications that they administer.

As a developer, this is both an exciting and challenging turn of events. Although new technologies and coding techniques must be learned, the user experience will be significantly improved as a result.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset