Microsoft & .NET.NETComing Soon to Windows: The Microsoft Shell (MSH)

Coming Soon to Windows: The Microsoft Shell (MSH)

With the advent of a new Command Line Interface (CLI) entitled MSH, Microsoft has greatly simplified server administration. Systems administrators can now learn about .NET classes while developers can easily extend the functionality by adding “MONAD” commandlets and providers; this is known as the “Glide Path”. This article will show the syntax usage for the CLI as well as how to create basic commandlets.

The Problem

Before we delve into some of the usage for the new command shell, let’s take a look at the weaknesses of the current shell to understand the direction Microsoft is moving in. First, there is little consistency with third-party utilities or between existing shell commands in cmd. For scripting, there is the functionally limited “BAT” (batch) method. Most importantly for the world of managing rich UI personal computers, it is very difficult to interact with some of the more graphical parts of previous Windows versions. Microsoft has stated that they made it a priority to try to make every single configuration available from both the command prompt and the GUI, from Windows 2003.

The Future

MSH (Microsoft Shell) allows the administrator to get more comfortable with the .NET framework classes if they so desire. This also serves to provide a common area of interest between programmers and sysadmins. Drives can be made out of providers and other rich functionality can be added easily to the command prompt. Other features, such as a “-whatif” directive, can serve to improve the quality assurance process of newly created providers or commandlets. Commandlets can allow the administrator or developer to extend the core functionality of the provided commandlets by piping information either from them, through them, or to them.

New Potential

Because all existing .NET classes are now fair game as additional functionality, there is a wealth of valuable material already floating around the .NET community. Imagine how easy it would be to write a commandlet that uses reflection on objects passed from remote servers for diagnostics, or even a system monitoring commandlet that hits a mission-critical Web service to ensure the Web service is still active. Through piping commands, the “monadic” components can even build on the functionality of other components to cascade results of one command as the inputs of other commandlets.

A commandlet’s syntax is in the form of “verb/noun [-parameters…]” with the handling of the parameters as mandated by the framework. This removes the flaws of the previous model where parameters could be in the form of /xyz or -xyz and it was up to the end user to read the documentation for each application to use the product. The new MSH provides a unified syntax where a user can already be prepared to script with new commandlets simply by building on the knowledge already attained through previous experiences.

Creating a Commandlet

/*
   Sample commandlet: get/machinesettings
*/
using System;
using System.Diagnostics;
using System.Management.Automation;

namespace GetMachineSettings
{
   /// <summary>
   /// Get/Machinesettings
   /// </summary>
   [CmdletDeclaration("get", "machinesettings")]
   public class GetPs: Cmdlet
   {
      public string MachineName=Environment.MachineName;
      public override void StartProcessing()
      {
         WriteObject("Current Machine Info");
         WriteObject("--------------------");
      }

      [ParsingMandatoryParameter]
      [ParsingPromptString("Enter either MACHINE for machine "
         +"information or ENVIRONMENT for environment variables")]
      public string InfoType;


      public override void ProcessRecord()
      {
         if (InfoType.ToLower() == "machine")
         {
            WriteObject(MachineName);
            WriteObject("Computer Name:    " +
                        Environment.MachineName);
            WriteObject("OS:               " +
                        Environment.OSVersion.ToString());
            WriteObject("System Directory: " +
                        Environment.SystemDirectory);
            WriteObject("Current User Name:" +
                        Environment.UserName);
            WriteObject("FrameworkVersion: " +
                        Environment.Version.ToString());
         }
         else if (InfoType.ToLower() == "environment")
         {
            WriteObject(MachineName);
            WriteObject(Environment.GetEnvironmentVariables());
         }
         else
         {
            WriteObject("Invalid selection; accepted values " +
                        "are MACHINE and ENVIRONMENT.");
         }
      }

   }

}

To begin, the first step in creating a commandlet is to import the System.Management.Automation namespace. This allows you to use the attributes necessary to create it.

[CommandDeclaration("verb","noun")]

The verb/noun pair in the CommandDeclaration attribute are the command pair registered in MSH when you go to run the shell. In this case, the pair is get/machinesettings because it will expose information about the machine and its settings. All commandlets derive from the Cmdlet base class that provides many methods that can be overloaded to expose even more functionality than this simple example.

The -ing and -ed suffixes added to the method names are the result of a new nomenclature for events in the 2.0 (1.2) framework. The first method shown is StartProcess(), which is called at the start of every process request. ConfirmProcessing and EndProccessing are also available, but in this example, most of the work is handled by the ProcessRecord method. This checks an input parameter to see which type of machine information the user wants, and writes out the objects to the console (or pipes to an output formatting commandlet at the request of the user).

The way MSH takes input parameters is through the attribute ParsingMandatoryParameter. We can specify the prompt when the user fails to provide the parameter on the commandline by using the ParsingPromptString attribute. If some security is needed, say for a server password, the ParsingPasswordParameter attribute is provided.

The Larger Picture

Now that an implementation of a commandlet has been shown, applications should be obvious. By extending this base class, a collection of server objects (the machines in your company) could be made, with this very same Environment information exposed via secure Web services. From there, a commandlet could very simply give an administrator instantaneous access to critical information about those machines.

One of the best new features about this shell is the fact that the actual objects are being written out. This means that the results can be stored inside an array, or passed actually as the original object to the next command in the pipe. For example, the dir command (just an alias to get/children) can be stored in an array by using variable definitions beginning with “$”. Note that comments start with “#”. The Length string is shown for illustration below, but in reality this may be any public property on the object being written out.

print $(get/children)[3]    #prints out the third file
$a = get/children           #stores dir in a varable $a
print $a[3].Length          #prints out how large $a[3] is.

For navigation, a stack is available so that you do not have to lose your trail if you are moving from one directory to another. Rather than using the available set/location, you can opt instead to push/location so that you may simply pop/location to return to your previous directory. Data stores are easy to deal with at the command prompt level now because they are made to mimic file systems. This means that if you want to expose something and have it easily navigable, you need only provide the appropriate navigation provider for your data store. In future articles, this will be shown step-by-step.

This example very simply writes out machine information based on user input. In future articles, we will see exactly how to navigate through collections of objects, as well as deal with input from other commandlets. In addition, some of the more complex syntax of shell scripting will be shown.

Download

Source code (MSH1_1.cs): MSH1_1.zip – 1 kb.

Note: This article contains references to prerelease code. The syntax of the released version may differ from what is stated here.

# # #

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Latest Posts

Related Stories